问题
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
Case 2: Now setting device time zone to san jose USA
NSLog of date shows 2014-07-09 07:00:01 +0000
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
Case 4: Setting device time to san jose USA
NSLog of date shows 2014-07-09 00:00:01 +0000
Can anybody please explain me what is happening in all these cases.
Regards Ranjit.
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/24650443/nsdate-behaviour-when-saving-to-plist