Quick tip (Objective-C): Formatting an RFC2822 date of an RSS feed using NSDateFormatter

Posted on January 25, 2009

Parsing an RFC2822 date of an RSS feed and formatting it using NSDateFormatter (e.g. "Tue, 16 Dec 2008 11:45:13 +0000" to "16. December 2008") is not easy as it seems. Fortunately there are already some helpfull tips and articles out there, such as fiam's solution described at "Parsing RFC2822 dates with NSDate", Anatoliy Kolesnick's article called "Parse Date from RSS to NSDate" or the helpful article "Advanced Strings In Cocoa" posted at CocoaCast.

All these solutions work great for me using the iPhone Simulator. But if you test your code on a real device (iPhone or iPod touch), you may run in an issue.

In my situation, all dates were not formatted well on my device, there are nil. It took me about 5 hours (I'm not kidding ;) ) to figure out, that the NSDateFormatter uses the current locale of a device for formatting dates.

On my device the locale is "German (Germany)" no matter if I change the settings to English or to any other language (Settings -> General -> International). As a result a month declared as "Dec" will be failed by NSDateFormatter on an iPhone using a German locale. It should be "Dez", the shortcut for "Dezember".

Solution

To format an RFC2822 date well on any foreign device you have to force the locale to "en_US". ( Note: That's not necessary for any English or American user ;) )

 1 //
 2 // Example of formatting the date string
 3 // "Tue, 16 Dec 2008 11:45:13 +0000"
 4 // to
 5 // "16. December 2008"
 6 //
 7 
 8 NSString *feedDateString = @"Tue, 16 Dec 2008 11:45:13 +0000";
 9 //
10 // A formatter to create a date using the RFC2822 date of a RSS feed
11 NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
12 // Note: We have to force the locale to "en_US" to avoid unexpected issues formatting data
13 NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
14 [inputFormatter setLocale: usLocale];
15 [usLocale release];
16 // set the format based on an RFC2822 date format
17 [inputFormatter setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss Z"];
18 // create a NSDate object using the NSDateFormatter
19 NSDate *formattedDate = [inputFormatter dateFromString: feedDateString];
20 // format the date created before to a format of your choice, such as "16. December 2008"
21 NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
22 [outputFormatter setDateFormat:@"d'.' MMMM yyyy"];
23 
24 NSLog(@"formattedDateString : '%@'", [outputFormatter stringFromDate:formattedDate]);
25 
26 [inputFormatter release];
27 [outputFormatter release];

BTW: For checking the locale on your device use the following snippet:

1 NSLocale *locale = [NSLocale currentLocale];
2 NSString *localeId = [locale displayNameForKey:NSLocaleIdentifier
3                               value:[locale localeIdentifier]];
4 
5 NSLog(@"localeId: '%@'", localeId);

-Jens

Any feedback?

comments powered by Disqus