Dateformatter'S Returns Nil For Specific Date Strings Without Time in Swift

DateFormatter's returns nil for specific date strings without time in Swift

You just need to set your date formatter calendar property:

Xcode 8.2.1 • Swift 3.0.2

let dateFormatter = DateFormatter()
dateFormatter.calendar = Calendar(identifier: .iso8601)
dateFormatter.locale = Locale(identifier: "es")
dateFormatter.dateFormat = "dd 'de' MMMM"
dateFormatter.date(from: "8 de octubre") // "Oct 8, 2000, 1:00 AM"

DateFormatter date from string returns nil when iPhone Date & Time 24-Hour Time is off

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.

Xcode 11, swift. Dateformatter always return nil

Update:

It would appear that it is a bug in Xcode. Trying your code in the viewDidLoad and setting a breakpoint causes the lldb description of the date to be nil, however it correctly prints the expected value out.

lldb missing value

You can see more about the bug at this SO post, thanks to OOPer for the link.

Currently this bug is still occurring in Xcode 11.2-beta


A couple of points

Use .dateFormat instead of .format

Use the correct quotation marks " instead of , also you should remove the space from your date format string.

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let date = dateFormatter.date(from: "2019-05-03")

Image showing above code working in Playgrounds

Dates are returning a nil when trying to compare oldest Swift

Here's how you can get the older date. I updated your code.


func getOldestDate(firstDate: String, secondDate: String, dateFormat: String ) -> String? {

let dateFormatter = DateFormatter()
dateFormatter.timeZone = .autoupdatingCurrent
dateFormatter.locale = .autoupdatingCurrent
dateFormatter.dateFormat = dateFormat

guard let date1 = dateFormatter.date(from: firstDate) else { return nil}
guard let date2 = dateFormatter.date(from: secondDate) else { return nil}

if firstDate > secondDate {
return dateFormatter.string(from: date2)
} else {
return dateFormatter.string(from: date1)
}
}

// call method
getOldestDate(firstDate: "10/20/2018", secondDate: "10/20/2017", dateFormat: "MM/dd/yyyy")

DateFormatter returns nil for some strings

For milliseconds, you should use SSS instead of sss like this -

dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

DateFormatter is returning nil date for a simple date string

Xcode Debugger has a bug as you can see in this post that it will show optional dates as nil even when parsing the date succeeds. If you print the optional date you will see the resulting date.

DateFormatter returns nil with specific combination of TimeZone and Locale

If you read the "Working With Fixed Format Date Representations" section of the DateFormatter docs, you'll find:

For most fixed formats, you should also set the locale property to a POSIX locale ("en_US_POSIX"), and set the timeZone property to UTC.

You should probably just follow the advice here... But here's possibly why SA and the Paraguay timezone produces nil.

Further down that section, there is a link to a technical Q&A where this is explained in more detail. The part that is most related to your problem is:

A user can change their calendar (using System Preferences > Language & Region > Calendar on OS X, or Settings > General > International > Calendar on iOS). In that case NSDateFormatter will treat the numbers in the string you parse as if they were in the user's chosen calendar. For example, if the user selects the Buddhist calendar, parsing the year "2010" will yield an NSDate in 1467, because the year 2010 on the Buddhist calendar was the year 1467 on the (Gregorian) calendar that we use day-to-day.

In the locale SA, the numbers of your date string seem to be interpreted using the Islamic Calendar. Take a look at today's date when formatted with en_SA and America/New_York.

let dateFormatter = dateOnlyDateFormatter("America/New_York", "en_SA")
let printDate = dateFormatter.string(from: .init())
print(printDate)
// 1443-10-26

Also take a look at the non-nil dates that is parsed by en_SA and America/New_York

let dateFormatter = dateOnlyDateFormatter("America/New_York", "en_SA")
let printDate = dateFormatter.date(from: date)
print(printDate)
// 2583-10-05 04:00:00 +0000

Notice that 10-05 is the first Sunday of the year 2583 (See this calendar). If Paraguay still uses the same DST rules as it does now in 2583, then it would mean that there is a DST gap transition at 2583-10-05 00:00:00, starting the DST period. The hour starting from 00:00:00 would be skipped, so 00:00:00 would not exist.

When parsing a date only, DateFormatter would try to set the time components to be 00:00:00 in the timezone of the formatter, but 00:00:00 does not exist, so the parsing fails.


In any case, just set locale to posix and timeZone to UTC when you have set dateFormat.

DateFormatter returns nil on specific devices

The returned date is correct, you can check that using the .timeIntervalSince1970 property. What happens is that when you print the date (which is actually just a TimeInterval, aka Double, a specific point in time, independent of any calendar or time zone), it's printing its description property, with the current device settings.

To print a date using your current locale, use this instance method:

let date = convertStringToDate(string: "06-10-18, 01:30 pm")
print(date.description(with: Locale(identifier: "en_US_POSIX")))


Related Topics



Leave a reply



Submit