Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 908
Ranjit Avatar asked Sep 30 '22 09:09

Ranjit


2 Answers

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.

like image 80
borrrden Avatar answered Oct 02 '22 22:10

borrrden


NSDate represents an absolute point in time and has nothing to do with timezones. What you're seeing and logging is the NSDate description which is fairly arbitrary across varying situations and useful only for debugging according to the Apple Docs

The representation is useful for debugging only.

There are a number of options to aquire a formated string for a date including: date formatters (see NSDateFormatter and Data Formatting Guide), and the NSDate methods descriptionWithLocale:, dateWithCalendarFormat:timeZone:, and descriptionWithCalendarFormat:timeZone:locale:

So, you can get your NSDate as stored since it's independent of any timezone information and use NSCalendar or NSDateFormatter to make all the conversions necessary to your app.

like image 34
spassas Avatar answered Oct 02 '22 23:10

spassas