[swift-users] DateFormatter bug

Quinn "The Eskimo!" eskimo1 at apple.com
Tue May 16 03:52:06 CDT 2017


On 16 May 2017, at 00:53, Ronaldo Faria Lima via swift-users <swift-users at swift.org> wrote:

> There is another important fact: 15 of October is when day light savings is effective in Brazil. 

Which means there’s no midnight on that day, right?

Last time I encountered this it was caused by an oddity in how NSDateFormatter handles dates that aren’t fully specified (in your case the date has year, month and day but not era, hour, minute and second).  It does this by getting the missing components from the `defaultDate` property.  This defaults to nil, yielding default components of 0, leading to a time of 2017-10-15 00:00:00, which doesn’t exist in the specified time zone.

The solution is to apply a default date with a time component.  For example:

1 import Foundation
2 
3 let fmt = DateFormatter()
4 fmt.timeZone = TimeZone(identifier: "America/Sao_Paulo")!
5 fmt.dateFormat = "yyyy-MM-dd"
6 fmt.defaultDate = Date(timeIntervalSinceReferenceDate: 12 * 60 * 60)
7 let aDate = fmt.date(from: "2017-10-15")
8 print(aDate)    // -> Optional(2017-10-15 12:00:00 +0000)

If you remove line 6, it prints nil.

The date I’ve chosen in line 6 (that is 2001-01-01 12:00:00 GMT) is fine in this case because it maps to a 10:00:00 in the specified time zone.  It could cause problems if your time zone is GMT-12, which can happen, so if you have to deal with arbitrary time zones then you need to provide a default date whose time components always make sense in local time.

Finally, I should stress that the above code is most definitely broken (try setting your default calendar to the Buddhist calendar and see what you get). If you’re working with fixed-format dates you must set the locale to `en_US_POSIX`, as described in QA1480 “NSDateFormatter and Internet Dates”.

<https://developer.apple.com/library/ios/#qa/qa1480/_index.html>

                   *                   *                   *

All of the above means that `DateFormatter` may not be the right option for you.  In many cases it’s better to parse a fixed-format date string into a set of date components and then build a date from those components.

Share and Enjoy
--
Quinn "The Eskimo!"                    <http://www.apple.com/developer/>
Apple Developer Relations, Developer Technical Support, Core OS/Hardware




More information about the swift-users mailing list