NSString *dateString = @"19/10/2014";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"dd/MM/yyyy"];
NSDate *myDate = [dateFormatter dateFromString:dateString];
Why myDate
is null for this specific date (19/10/2014)??
If i change the dateString
to @"25/10/2014"
, dateFormatter
return the date correctly... What is wrong with my code?
* This code returns null when my iPhone time zone is "Brasilia, Brasil". When my time zone is "Washington, D.C., EUA" for example, the code returns the correct date.
Rob Mayoff gave an excellent explanation and solution to this problem. As Rob pointed out, midnight on 19/10/2014 doesn't exist in the Brazilian time zone.
Another possible solution is to tell the date formatter to be "lenient". In that case it will return the first valid date on the given day:
The result is "2014-10-19 03:00:00 UTC" which is "2014-10-19 01:00:00 BRST", i.e. the first valid date on that day when daylight saving time started.
If your date you wish to format is a specific format that you want all devices in all regions to understand, you will need to set a locale on your date formatter.
Without doing so, the date formatter will default to the devices locale. This would mean that Brazil's date format is seemingly not dd/MM/yyyy
You can force your date formatter to use a specific locale like so:
Hope this helps
W
We can reproduce your problem by explicitly setting the time zone to “Brazil/East”:
Here's the output:
Since you didn't give a time in your
dateString
, the system assumes midnight. But midnight on that date doesn't exist in the Brazilian time zone.Brazil changes from BRT (daylight-saving time zone) to BRST (non-daylight-saving time zone) on October 19, 2014, skipping directly from the last moment of “18/10/2014” to “19/10/2014 01:00:00”.
Since “19/10/2014 00:00:00” doesn't exist,
NSDateFormatter
returnsnil
. I think this is bad behavior on the part ofNSDateFormatter
, but we have to deal with it.-[NSDateFormatter dateFromString:]
eventually callsCFDateFormatterGetAbsoluteTimeFromString
, which uses theudat_parseCalendar
function from the International Components for Unicode (icu) library to parse the date.You can work around the problem by making the parser use noon instead of midnight as the default time. No time zones change to/from daylight saving time at noon. Let's write a helper function that returns noon of some arbitrary date in a given time zone:
Then we set the date formatter's
defaultDate
to this noon date:And here's the output: