5

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.

Ranjit
  • 4,576
  • 11
  • 62
  • 121
  • +1 well structured question. Do you get the same date/time in the console when you log the date object using: `NSLog(@"date=%@", date);`? – trojanfoe Jul 09 '14 at 09:59
  • Thanks, In which case?\ – Ranjit Jul 09 '14 at 10:01
  • Well the above `NSLog()` call will use `[NSDate description]` to print the date, which is the date in UTC. Therefore you have proved the effects of setting dates with specific time zones and saving them in UTC, which is why the dates change in the plist. – trojanfoe Jul 09 '14 at 10:09
  • @trojanfoe, when time zone is UTC and device time zone is san jose , why in plist it is 5:30:01am, I can understand for india region, because the offset it is UTC+5:30. – Ranjit Jul 09 '14 at 10:19
  • Err, I don't understand that to be honest. It's possible there is an error in your code (you have the same time for both india and california, so something is wrong here). – trojanfoe Jul 09 '14 at 10:23
  • ok, @trojanfoe, can you explain me about the time in first two cases? – Ranjit Jul 09 '14 at 10:26
  • @trojanfoe It takes a bit of time to understand fully, but the thing to keep in mind is that the time zone specified by `NSCalendar` will be used in calculating the final `NSDate` object. The first two are implicit, and the second two are explicit. However, the final string will always be Indian Standard Time. – borrrden Jul 09 '14 at 10:28
  • As a follow up to that comment I suppose I can see why it should output differently, but there are probably circumstances surrounding the fact that it always outputs Indian Standard Time instead of the local device time zone (maybe it is cached during app launch, etc) – borrrden Jul 09 '14 at 10:50
  • Hey @borrrden, thanks for the detailed information, I tested by uninstalling the app and running again, but then also I get same results, so I think your speculation doesnt hold true. – Ranjit Jul 09 '14 at 11:39
  • @HotLicks, So what you suggest? – Ranjit Jul 09 '14 at 11:40
  • @trojanfoe, if you think, I have made any misatke in my code, if you get time, please test out, and let me know what results you get – Ranjit Jul 09 '14 at 11:41
  • I'm looking at it again. What's unclear is what the original NSDate object was. You should have NSLogged that along with dumping the plist date. I'm thinking the plist is saved as UTC but you're logging different UTC times. – Hot Licks Jul 09 '14 at 11:42
  • @HotLicks, no, I have shown all the 4 cases, with UTC and without UTC – Ranjit Jul 09 '14 at 11:43
  • You modified your code each time, so we don't know what it was for a given case. And you don't, with each plist snapshot, have the NSLog of your NSDate object, so we know what the NSDate *really* was. – Hot Licks Jul 09 '14 at 11:46
  • ok, I will update my question for the logs – Ranjit Jul 09 '14 at 11:46
  • Aha! What you're seeing is probably the UTC time in the plist being converted to your Mac's local time by plist display function. – Hot Licks Jul 09 '14 at 11:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/57017/discussion-between-ranjit-and-hot-licks). – Ranjit Jul 09 '14 at 11:59
  • @HotLicks, if its that, can you test in your machine and let me know whether you get same results – Ranjit Jul 09 '14 at 13:04
  • @HotLicks Has a good point. Open the plist in a text editor if you can and see how it is really saved. The plist editor might be converting it from a number to a string on demand. – borrrden Jul 10 '14 at 00:56

2 Answers2

3

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.

borrrden
  • 33,256
  • 8
  • 74
  • 109
  • Hey @borrrden, thanks for the detailed information, I tested by uninstalling the app and running again, but then also I get same results, so I think your speculation doesnt hold true. – Ranjit Jul 09 '14 at 11:37
  • you say that for more control use NSDateFromatter, but where does that come into picture, bcoz, I am saving only dates, I have not converted them to strings – Ranjit Jul 09 '14 at 11:54
1

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.

spassas
  • 4,778
  • 2
  • 31
  • 39
  • So do you mean that if my app is used by an US user, then the plist will contain 5:30:01 am for dates he/she store? – Ranjit Jul 09 '14 at 10:22
  • Not necessarily, but it does not make any difference for you. The `NSDate` will always point to the same point in time. So, as I wrote above, you just retrieve it and translate it to your desired format with the use of `NSCalendar`or `NSDateFormatter` – spassas Jul 09 '14 at 10:25
  • So you say that, it doesnt matter whether the plist contains 5:30:01 or 12:30:01 right? because the second case is 12:30:01 – Ranjit Jul 09 '14 at 10:27
  • I think that the answer by @borrrden wraps it up very nicely. – spassas Jul 09 '14 at 10:35