Search code examples
iosnsdateplistnsdatecomponentsnstimezone

NSDate behaviour when saving to plist


I am creating a date from [NSdate date] and saving it to plist, Here is how I am creating a date

- (void)applicationWillResignActive:(UIApplication *)application
{
    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
   // [gregorian setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];


    NSDateComponents *weekdayComponents = [gregorian components:(NSDayCalendarUnit | NSYearCalendarUnit | NSMonthCalendarUnit  | NSMinuteCalendarUnit)fromDate:[NSDate date]];
    NSInteger day    = [weekdayComponents day];
    NSInteger month  = [weekdayComponents month]; 
    NSInteger year   = [weekdayComponents year];

    NSDateComponents *timeZoneComps=[[NSDateComponents alloc] init];
    [timeZoneComps setDay:day];
    [timeZoneComps setMonth:month];
    [timeZoneComps setYear:year];
    [timeZoneComps setHour:00];
    [timeZoneComps setMinute:00];
    [timeZoneComps setSecond:01];    


    NSDate *date = [gregorian dateFromComponents:timeZoneComps];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"file.plist"];

    NSMutableDictionary *d = [NSMutableDictionary new];
    [d setObject:date forKey:@"my-date"];

    [d writeToFile:filePath atomically:YES];
}

I have tested few cases

Case 1: without setting timezone to NSCalendar object gregorian above(by default it will take local time zone) and setting time zone in device to india, I saved the date to plist and this is what I got

NSLog of date shows CurrentDate:2014-07-08 18:30:01 +0000

enter image description here

Case 2: Now setting device time zone to san jose USA

NSLog of date shows 2014-07-09 07:00:01 +0000

enter image description here

Case 3: Setting timezone of NSCalendar object, gregorian above to "UTC", and setting time zone in device to India, this is what I got in plist

NSLog of date shows 2014-07-09 00:00:01 +0000

enter image description here

Case 4: Setting device time to san jose USA

NSLog of date shows 2014-07-09 00:00:01 +0000

enter image description here

Can anybody please explain me what is happening in all these cases.

Regards Ranjit.


Solution

  • This is because of the way you are handling NSDate. Once you convert something into an NSDate then you lose all time zone information, and when you write it to the plist it will be written in your current time zone as it is converted back into a string. So let's go through the scenarios one by one.

    All scenarios follow this flow NSDate -> NSDateComponents -> NSDate -> String

    1) NSDate: 2014-07-09 XX:XX:XX IST -> NSDateComponents 2014-07-09 00:00:01 IST -> NSDate 2014-07-09 00:00:01 IST -> 09-Jul-2014 12:00:01 am

    2) NSDate: 2014-07-09 XX:XX:XX PST -> NSDateComponents 2014-07-09 00:00:01 PST -> NSDate 2014-07-09 12:30:01 IST -> 09-Jul-2014 12:30:01 pm

    3) NSDate: 2014-07-09 XX:XX:XX UTC -> NSDateComponents: 2014-07-09 00:00:01 UTC -> NSDate: 2014-07-09 05:30:01 IST -> 09-Jul-2014 5:30:01 am

    4) Same as 3 since you manually specified the time zone

    Just remember that NSDate does not care about time zones. It is just a point in time. 2014-07-09 00:00:01 UTC and 2014-07-09 05:30:01 IST are the exact same time in terms of NSDate (426556801 seconds ahead of 2001-01-01 00:00:00 GMT). The reason why they differ in the plist is because you are choosing (implicitly) the local time representation of your NSDate. If you need more control, use NSDateFormatter.

    EDIT Come to think of it you could argue that the results should be different, but the way that NSDate outputs to a plist is proprietary so it looks like for some reason it keeps using Indian Standard Time. Speculation could include maybe that you didn't kill your app between setting the time zone or something.

    SECOND EDIT Actually I'm interested in what the raw plist is holding. You are using an editor to view it, and it might be converting it to your Mac's local time when displaying it.