Why isn't my time zone being saved into my NSD

2019-01-23 04:40发布

问题:

I must initialize an NSDate object from NSString in objective-c. I do it like this:

NSString *dateString = [[webSentence child:@"DateTime"].text stringByReplacingOccurrencesOfString:@"T" withString:@" "];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-mm-dd HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Budapest"]];

NSDate *date = [[NSDate alloc] init];
date = [dateFormatter dateFromString:dateString];

E.g: when I try it with string value @"2011-01-02 17:49:54" I get an NSDate 2011-01-02 16:49:54 +0000. As you can see there is a one hour difference between the two values. NSDate has a wrong value, it should be exactly the same I defined in my string in the timezone I set in dateFormatter. It seems it uses my date defined it string as UTC, even if I set its timezone to "Europe/Budapest". How can I fix this problem?

Thanks!

回答1:

Two things:

1) you have an error in your date format string. You should use MM for month, not mm (lowercase mm is for minutes)

2) after you create you NSDate object, you'll need to use the NSDateFormatter method stringFromDate: to generate a date string localized to a particular timezone. If you just do a straight NSLog() on the NSDate object it will show the date as GMT by default (GMT is one hour behind Budapest time)



回答2:

NSDate stores dates relative to a standard reference date. From the class docs:

"The sole primitive method of NSDate, timeIntervalSinceReferenceDate, provides the basis for all the other methods in the NSDate interface. This method returns a time value relative to an absolute reference date—the first instant of 1 January 2001, GMT."

NSDate does not itself have any concept of time zones. So the NSDateFormatter did the right thing: it converted a date which you told it had a GMT offset (by specifying a time zone), and gave you a "normalized" NSDate for that date.

If you want to see the date represented in the Europe/Budapest time zone, either use your existing date formatter (-stringFromDate:) or the appropriate NSDate description method (e.g. -descriptionWithCalendarFormat:timeZone:locale:).

P.S.- You don't need an alloc/init at all in your code as written. In non-ARC that would be a leak.

P.P.S.- Your date format is incorrect and giving nonsensical results. I've gone ahead and cleaned up your code as follows (tested under ARC):

NSString *dateString = @"2011-09-02 17:49:54";
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *tz = [NSTimeZone timeZoneWithName:@"Europe/Budapest"];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
[dateFormatter setTimeZone:tz];

NSDate *date = [dateFormatter dateFromString:dateString];
NSLog(@"%@", [dateFormatter stringFromDate:date]);
NSLog(@"%@", [date descriptionWithCalendarFormat:nil timeZone:tz locale:nil]);