Search code examples
iosnsdatensdateformatternslocale

when to set the NSLocale for the NSDateFormatter ?


In my app , Im using following code to convert string to date before inserting the date into the database.

However this code fails for the users in UK, they have the Region set to UK, and Timezone set to London.

This works for the users in the US as their locale is en_US. So that says, this code works fine for en_US locale but not en_GB locale.

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setLocale:[NSLocale currentLocale]];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T1'HH-mm-ss-SSS"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]]; //doing this as timestamp stored in server is based on UTC, hence I'm using UTC instead of systemTimeZone
 date = [dateFormatter dateFromString:theDate];

The passed string is : 2014-6-26T121-21-6-000

If I set the locale as follows, instead of currentLocale for all the users across the world:

[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];

then the code works, but I would like to know if this cause any issues in future?

Why we need set the locale property for converting the dates ?

Why the currentLocale fails in my case but not the en_US locale even though the date format is matched properly ?


Solution

  • Whenever you’re dealing with ISO 8601 or RFC 3339 dates (i.e. dates exchanged with web services and/or stored as a string in some data store) use en_US_POSIX. See Technical Note 1480.

    Or one can use NSISO8601DateFormatter and you don’t have to deal with this locale silliness. E.g.

    NSString *string = @"2014-06-26T12:21:06.000Z";
    
    NSISO8601DateFormatter *formatter = [[NSISO8601DateFormatter alloc] init];
    formatter.formatOptions = NSISO8601DateFormatWithInternetDateTime | NSISO8601DateFormatWithFractionalSeconds;
    
    NSDate *date = [formatter dateFromString:string];
    

    Also, standard representations of ISO 8601 and RFC 3339 datetime strings, you’d generally use a format like 2014-06-26T12:21:06.000Z where:

    • the hour is less than 24;
    • numbers are zero-padded;
    • separators between hours and minutes and seconds are :;
    • the separator between seconds and milliseconds is .; and
    • you'd often add Z at the end of the string to unambiguously designate that the time string is in GMT/UTC/Zulu.