How to check if the date is valid, before making a SQL query using
request.predicate = NSPredicate (format: "% # <= AND myDate% #> = myDate" startDate, endDate)
an error occurs with the leap years, like 30 of February 2016.
// code form comment...
let startDate:NSDate = dateFormatter.dateFromString("2016-10-01")!
let endDate:NSDate = dateFormatter.dateFromString("2016-10-29")!
The return value of a date generated by DateFormatter's date(from:) method is an optional. If nil is returned the date is invalid, otherwise it's valid.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
if let date = dateFormatter.date(from:"2016-02-30") {
print(date) // if this prints date is valid
}
else {
print("Date is Invalid") // if this prints date is invalid
}
A Date cannot be instantiated with an invalid date string that is outside of the realm of real calendar dates.
If what you are asking is whether a date falls between two other dates, see here: https://stackoverflow.com/a/40057117/1694526
Use DateFormatter class... It can be used to check any string whether it is a valid date or not and accordingly the string can be converted into nsdata.
Related
This question already has an answer here:
DateFormatter doesn't return date for "HH:mm:ss"
(1 answer)
Closed 2 years ago.
I am working on an app that initializes dates from strings returned from the backend. The dateString is returned using the following format: "2020-03-05T09:00:00+00:00"
The method I have to do the conversion is:
extension Date {
static func convertDate(_ dateString: String?) -> Date? {
guard let dateString = dateString else { return nil }
let dateFormatter = DateFormatter()
dateFormatter.setLocalizedDateFormatFromTemplate("yyyy-MM-dd'T'HH:mm:ssZZZZZ")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
return dateFormatter.date(from: dateString)
}
}
Everything was working fine until someone reported that if the user switches off "24-Hour Time" in settings the method above returns nil.
What am I doing wrong?
Thank you
You're using a very standardized timestamp format, which allows you to take advantage of the ISO8601DateFormatter.
let dateString = "2020-03-05T09:00:00+00:00"
let df = ISO8601DateFormatter()
df.formatOptions = [.withInternetDateTime]
if let date = df.date(from: dateString) {
print(date) // 2020-03-05 09:00:00 +0000
}
If a machine (like your server) is generating the timestamp then it will (should) always be in zulu time (GMT) so you don't need to do anything beyond this. You could specify a time zone but there isn't a point since the string will always zero it out for you.
df.timeZone = TimeZone(secondsFromGMT: 0)
This string represents an absolute moment in time. If you need a relative moment in time, such as the local time from the source, you'll need to identify that time zone and apply it here, which is also very straighforward.
I'm writing a unit test to check that my conversion from a date to string and back is successful.
I convert it to a string via:
func convertDateToString(date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return dateFormatter.string(from: date)
}
and convert it back via:
func convertStringToDate(string: String) -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return dateFormatter.date(from: string)!
}
If you try to use the Equatable protocol on the pre-conversion date and post-conversion date it says they are not the same. However, if you convert both pre and post dates to strings and compare them, they are Equatable. This is what it says when I run XCAssertEqual on pre and post dates:
XCTAssertEqual failed: ("2020-01-22 19:35:40 +0000") is not equal to ("2020-01-22 19:35:40 +0000")
Which looks pretty identical to me. I even tried converting the pre-conversion date to a string and back to check if the dates were equal and they still weren't
The problem there is that Date is stored as a FloatingPoint value (timeIntervalSinceReferenceDate). There is fractional seconds being discarded there when converting your Date to String and back to Date. Take a look at post.
This question already has answers here:
Convert date string swift
(3 answers)
Closed 5 years ago.
So I took a current date and did stored theDate.description (which is something like 5/3/17, 10:16 AM) into my firebase database. When retrieving the data from my database, I want to be able to sort by that date, so I want to convert it back to a Date object. How do you do that?
I looked at some previous posts but they were all either old (with NSDate) or just didn't work. Thanks!
for (key, value) in dictionary {
print("\n\nKEY AND VALUE")
print(key)
print(value)
print("\n\n")
var date1: Date = Date()
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy"
date1 = dateFormatter.date(from: value)!
let temp = historyListItem(keyEntered: key, dateEntered: date1)
self.historyKeysAndDateArray.append(temp)
print(value)
}
^It gives me the error: fatal error: unexpectedly found nil while unwrapping an Optional value at this line: date1 = dateFormatter.date(from: value)!
value is a string in this format: 5/2/17, 3:15 PM
There are a few issues here. The main one being the wrong date format for the string. Here's the proper code with some other cleanup:
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "M/d/yy, h:mm a"
for (key, value) in dictionary {
print("\n\nKEY AND VALUE")
print(key)
print(value)
print("\n\n")
if let date1 = dateFormatter.date(from: value) {
let temp = historyListItem(keyEntered: key, dateEntered: date1)
self.historyKeysAndDateArray.append(temp)
print(value)
}
}
Don't force-unwrap optionals. Your app will crash.
Also, create the formatter before the loop. It will be much more efficient.
The date/time you are trying to format is: 5/2/17, 3:15 PM
Yet your dateFormatter is: dateFormatter.dateFormat = "dd/MM/yyyy"
The dateFormat much match exactly to convert that string to a date type.
Where is the time and am/pm
Say time string value is "7:00 AM" call it reminder time.
Now all I need to do is compare this time with the current dates time say its "9:00 AM" if reminder time is later than current time - return true else false. This is the format "h:mm a" for date formatters.
Simple right? It should be but I have burned too much time on this. I can get hour and minute values but when the AM/PM is considered it gets harder.
I just want to compare two time values and determine if the first is later or after the second one. The date is always today or current date so I only care about the time part of the date. Of course you have to convert to dates to do the comparison but current date is easy to get however date from "7:00 AM" string does not seem to work right in comparisons.
Anyone have a function to do this?
Thanks.
the approach would be lets date the Date() object from your current time object so you will get
default date + your time = 2000-01-01 00:00:00 +your time (7.00 AM or 9.00 PM)
now we will get the current time from today only, in same format. (Only time)
it will be something like 3.56 PM
now again we will convert this 3.56 PM to Date() with default date as prev. so now we will have two date time object with same Date(2000-01-01) and respective times.
2000-01-01 7:00:00 => this will your 7.00 AM with default date
2000-01-01 15:56:00 => this will be current time with default date
now we will compare two date object.
Check the fiddle Fiddle
func CompareMyTimeInString(myTime:String)->Bool
{
// create the formatter - we are expecting only "hh:mm a" format
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm a"
dateFormatter.locale = Locale.init(identifier: "en_GB")
// default date with my time
var dt_MyTime = dateFormatter.date(from: yourTime)!
// current time in same format as string "hh:mm a"
var currentTimString = dateFormatter.string(from: Date());
print("Current Time is - "+currentTimString);
// current time with default date.
var dt_CurrentTime = dateFormatter.date(from: currentTimString)!
// now just compare two date objects :)
return dt_MyTime > dt_CurrentTime;
}
// then call it like
var yourTime = "7.00 AM"
var isDue = CompareMyTimeInString(myTime:yourTime);
print(isDue);
My solution was as follows.
private func ReminderAfterCurrentTime(reminderTimeString: String) -> Bool {
//Compare the two time strings and if reminderTimeString is later than current time string
//return true since Reminder is after current time.
//Get the current date and time
let currentDateTime = Date()
// Create calendar object
let calendar = NSCalendar.current
// Get current date hour and minute values for comparison.
let currentHourValue = Int(calendar.component(.hour, from: currentDateTime))
let currentMinuteValue = Int(calendar.component(.minute, from: currentDateTime))
//Now get a date from the time string passed in so we can get just the hours and minutes to compare
let dateformatter = DateFormatter()
dateformatter.dateStyle = DateFormatter.Style.none
dateformatter.timeStyle = DateFormatter.Style.short
//Now get the date using formatter.
let reminderDateTime = dateformatter.date(from: reminderTimeString)
print("reminderDateTime = \(reminderDateTime)")
//Get reminder hour and minute for comparison.
let reminderHourValue = Int(calendar.component(.hour, from: reminderDateTime!))
let reminderMinuteValue = Int(calendar.component(.minute, from: reminderDateTime!))
print("currentHourValue = \(currentHourValue)")
print("currentMinuteValue = \(currentMinuteValue)")
print("reminderHourValue = \(reminderHourValue)")
print("reminderMinuteValue = \(reminderMinuteValue)")
//This works due to 24 hour clock. Thus AM/PM is already taken into account.
if currentHourValue < reminderHourValue {
return true
}
//Check for same hour then use minutes
if currentHourValue == reminderHourValue {
if currentMinuteValue < reminderMinuteValue {
return true
}
}
//Otherwise return false
return false
}
I have an attribute in CoreData which accepts a date value. I just want to get the current date and save it in this format "dd/mm/yyyy" . But don't know how. Thanks
If you're storing it as Date, then you have no control over the format until you try to present the returned value somewhere, and you just store Date()
If you're storing it as shown, then you need to use a DateFormatter to create the string you need
Here you can store date in coreData as shown in format
let date = NSDate()
var dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy"
var dateString = dateFormatter.string(from: date as Date)
store dateString in your coreData
To save dates in Core Data I have created the following extension
extension Date {
/**
Formats a Date
- parameters format: (String) for eg dd-MM-yyyy hh-mm-ss
*/
func format(format:String = "dd-MM-yyyy hh-mm-ss") -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
let dateString = dateFormatter.string(from: self)
if let newDate = dateFormatter.date(from: dateString) {
return newDate
} else {
return self
}
}
}
To set a date value of a field
let date = Date()
entity?.setValue(date.format(), forKey: "updated_at")
Note: You may see date saved as timestamp when you open your database. Please refer to the following issue NSDate being saved as timestamp in CoreData
You can also pass you own date formats in the "format()" extension to get different types of dates in the application