Kevin Ferrell

Reference Dates in iOS and the 24 Hour Clock

I recently came across a bug in one of my iOS apps due to NSDateFormatter’s handling of a user’s 24 Hour clock setting on their iPad. The app automatically synchronizes a series of objects to the user’s device when the app launches. Typically, the sync service will get the max LastModified from each of the object tables and then uses that date to download any updates. However, when the app performs its first data sync it uses a hard-coded reference date in the past to get a full data set:

NSString *distantPast =@"01/01/2000 12:01 AM";
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:@"MM/dd/yyyy hh:mm a"];
NSDate *lastModDate = [formatter dateFromString:distantPast];

The bug occurs when a user has set their iOS clock to a 24 hour format instead of the default 12 hour format. When a user has their clock set to the 24 hour format it changes the default NSDateFormatter local which invalidates the date format above and generates an error. This results in a null NSDate, which broke the sync service in my app.

I found the simple solution to the issue in Apple’s Technical QA #1480. The technical doc explains that if you’re parsing a fixed date that isn’t going to be displayed to the user you should not use the default NSLocal with NSDateFormatter because this can change based on where the user is located. The 24 hour clock setting also changes the default NSLocal setting. Since date/time in the example code above isn’t a valid date when using a 24 hour clock, the dateFromString: method returns nil.

This can be fixed by specifying a NSLocal for your NSDateFormatter:

NSString *distantPast =@"01/01/2000 12:01 AM";
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:@"MM/dd/yyyy hh:mm a"];

NSLocale *enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
[formatter setLocale:enUSPOSIXLocale];

NSDate *lastModDate = [formatter dateFromString:distantPast];

This was a tricky little bug that had been in a production app for over a year when I discovered it. During that entire time we apparently only had one user that used a 24 hour clock setting!

Discussion Closed

New comments are not allowed on this post.