NSDictionary returns wrong values for NSDate in other Time Zones

I'm storing dates in an NSDictionary and even though it creates a very weird value when stored, it returns the correct time in my time zone. However, if I change my time zone and read the value, I don't get values offset by the hour - I get weird values:

Original time in my date object in NY: 9:10:20 am

Value stored in Dict: Dict {Time = "0001-01-01 14:06:22 +0000";}

Value returned from objectForKey:

New York 9:10:20 am
Chicago 8:15:46 am
Denver 7:06:26 am
California 6:13:24 am

I'll post my code here but I'm at a loss to figure out how to fix this.

NSLog(@"Original Date %@",date);
NSDictionary *myDict = [[NSDictionary alloc] initWithObjectsAndKeys:date,@"Time", nil];
NSLog(@"MyDict %@", myDict);
NSDate *tempDate = [myDict objectForKey:@"Time"];
NSLog(@"tempDate %@",tempDate);

Even if I format it, it is wrong:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[dateFormatter setDateStyle:NSDateFormatterNoStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];

[dateFormatter setDateFormat:@"h:mm:ss a"];
return [dateFormatter stringFromDate:date];

The good news is that it seems to convert to/from NSDictionary in whatever time zone it was created in, but this is a big issue for anyone that travels with our app.

Thoughts about what causes this and what can fix it? If the app wasn't already released and in use, I'd simply change my storage format. I need to have this work with existing data.

This is happening with code compiled on iOS 16 Xcode 14 running on an iPad Pro running iOS 15.6.1

Your examples all show times without dates. Is that what you’re attempting to store?

This matters because, if your goal is to store times without dates, NSDate is the wrong type. NSDate stores an exact point in time. Under the covers it’s a Double count of seconds from the GMT reference date. So:

  • It knows nothing about time zones.

  • It can’t store a time without storing the date on which that time occurred.

The last one is the kicker because some times don’t exist on some dates. For more on that, see Parsing Dates Without Times.

If your goal is to just store a time, it’s better to store that as a tuple of hour/minute/second. Or you can use an NSDateComponents value and populate just those properties.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

NSDictionary returns wrong values for NSDate in other Time Zones
 
 
Q