22

Here is my code :

NSString *_date = @"Tue, 23 Nov 2010 16:14:14 +0000";
NSDateFormatter *parser = [[NSDateFormatter alloc] init];
[parser setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss '+0000'"];
[parser setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
NSDate *date = [parser dateFromString:_date];

This doesn't run : 'date' is set to 'nil'. I tried with

[parser setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss ZZZ"];

With no more success...

Do you have any idea ?

Thanks in advance

Harkonnen
  • 791
  • 2
  • 8
  • 21
  • 1
    What locale is your device/simulator set to? This will only work if the locale is set to English. – Ole Begemann Nov 23 '10 at 16:31
  • My locale is French...I didn't thought about that, shame on me :) Is there a way to make this code compatible with most current locales without changing the initial date ? – Harkonnen Nov 23 '10 at 17:00
  • 1
    You can tell the NSDateFormatter to use a specific locale for parsing (eg. en_US_POSIX). See [Apple QA1480](http://developer.apple.com/library/ios/#qa/qa2010/qa1480.html). –  Nov 23 '10 at 17:09
  • It does *run*; it just doesn't give you the result you wanted. – Peter Hosey Nov 24 '10 at 04:00

2 Answers2

53

Add this line:

NSDateFormatter *parser = [[NSDateFormatter alloc] init];
[parser setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease]];

and it will work. By default, NSDateFormatter uses the system's current locale, which can vary depending on the current user's preferences. The date string above (@"Tue, 23 Nov 2010 16:14:14 +0000") contains English words ("Tue", "Sep") that would potentially not be recognized by the date formatter if the locale would be set to anything other than English.

Moreover, users from non-western cultures might use locales that use a different calendar than the Gregorian calendar that's used in the western world. If you did not explicitly set the locale, the date formatter might be able to parse the date but the resulting NSDate would represent a whole other point in time.

The locale identifier @"en_US_POSIX" is meant for this purpose. It is guaranteed to not change even if the @"en_US" locale should someday change its default settings.

Ole Begemann
  • 135,006
  • 31
  • 278
  • 256
  • It'd be great if you can explain why setting the locale solves the problem. In other words, why would `dateFromString` work only if the locale is set to US English? – Andrew Sep 10 '12 at 04:37
  • 1
    @andrewap: I updated my answer with an explanation (and I changed my recommendation from `@"en_US"` to `@"en_US_POSIX"`, which is the more future-proof solution. – Ole Begemann Sep 10 '12 at 08:06
  • @OleBegemann : This line also solved my problem except that my string had was the following : 2013-02-15T11:12:12Z. The string doesn't contain English words so I am not sure why I need this line to make it works. Do you know why I had to add this line? – MartinMoizard Jan 21 '13 at 12:10
  • @MartinMoizard agreed, I'm seeing the same problem, why the issue if no English words? Is it the T or the Z somehow? – steve May 26 '13 at 00:31
  • @MartinMoizard A string like that will require a calendar to be set in order for the formatter to work (day, year and month numbers depend upon the calendar being used), and it would be reasonable if, when using an `NSDateFormatter` with a `locale` set but a nil `calendar`, the `NSLocaleCalendar` associated with the locale was used (which in your case would, appropriately, be the Gregorian calendar). However, in practice, I don't see this behaviour; I need to explicitly set a calendar in my test cases or my formatter doesn't work, with or without a locale. I'm currently as confused as you. – Mark Amery Aug 07 '13 at 13:48
3

The timezone specifier is 'z', so your string should be:

[parser setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss z"];
Denis Hennessy
  • 7,243
  • 4
  • 25
  • 31