I want to output a date (that has relative dates, e.g. Today, Yesterday etc.) and time (respecting the 12/24 hours setting on the iOS device) E.g.
Configuring an NSFormatter like this (and using stringFromDate:) does not work:
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale: [NSLocale autoupdatingCurrentLocale]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle]; // doesn't respect am/pm setting on iOS device (grrr!)
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setDoesRelativeDateFormatting:YES]; // but does get relative dates
This gives you relative dates, but defaults to the 12/24 setting for the locale, e.g. 12 hours for US and 24 hours for UK. (Why Apple think UK people like 24 hours clocks, I don't know...)
A work around that I've adopted uses two NSDateFormatters, one for the date and one for the time. It appears that when you configure an NSDateFormatter with a dateStyle of NSDateFormatterNoStyle and a timeStyle of NSDateFormatterShortStyle, then it does respects the 12/24 hour setting. (So it's just when you have BOTH date and time styles set that there is trouble.)
I've included my work around below in case anyone else has a similar issue. Is there an easier way to do this? The work around seems somewhat awkward and it is not clear how confident I should be it will continue working in future revisions of iOS.
Work around
- (NSString*) humanRelativeDateAndTimeAlt: (NSDate*) date;
{
NSDateFormatter* relativeDateFormatter = [[NSDateFormatter alloc] init];
[relativeDateFormatter setLocale: [NSLocale autoupdatingCurrentLocale]];
[relativeDateFormatter setTimeStyle:NSDateFormatterNoStyle]; // no time for this formatter
[relativeDateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setDoesRelativeDateFormatting:YES]; // relative dates
NSString* datePart = [[self relativeDateFormatter] stringFromDate:date];
NSDateFormatter* timeDateFormatter = [[NSDateFormatter alloc] init];
[timeDateFormatter setLocale:[NSLocale autoupdatingCurrentLocale]];
[timeDateFormatter setDateStyle: NSDateFormatterNoStyle]; // no date for this formatter
[timeDateFormatter setTimeStyle: NSDateFormatterShortStyle]; // does respect 12/24 hour setting
NSString* timePart = [timeDateFormatter stringFromDate:date];
int skipZero = 0; // extra code to remove leading zero if present
if ([[timePart substringToIndex:1] isEqualToString:@"0"]) skipZero = 1;
[relativeDateFormater release];
[timeDateFormatter release];
return [NSString stringWithFormat:@"%@ %@", datePart, [timePart substringFromIndex:skipZero]];
}
The reason for this behaviour is Locale, set the correct Locale, Set the local of your NSDateFormatter to en_US_POSIX will fix this. It works for both 24-hour and 12 hour format.
From Apple doc:
On iPhone OS, the user can override the default AM/PM versus 24-hour time setting (via Settings > General > Date & Time > 24-Hour Time), which causes NSDateFormatter to rewrite the format string you set.
Reference: What is the best way to deal with the NSDateFormatter locale “feature”?