简体   繁体   中英

Why does stringFromDate NSString still have GMT time even though I set timezone on the NSDateFormatter?

The output for the actual NSDate object ( firstTime ) is what I want it to be (the iOS device's time). The NSString object ( secondTime ) still seems to be showing the GMT time (which is 4 hours ahead of my local time, EST) even though I set the date formatter ( df ) to the localTimeZone. Why is it not working?

NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"HH:mm:ss"];
[df setTimeZone:[NSTimeZone localTimeZone]];

NSDate *firstTime = [NSDate dateWithTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT] sinceDate:[NSDate date]];
NSLog(@"%@", firstTime);
NSString *secondTime = [df stringFromDate:firstTime];
NSLog(@"%@", secondTime);

Output:

FIRST TIME: 2014-05-07 17:41:29 +0000, SECOND TIME: 13:41:29

An NSDate does not have a time zone. Read that five times until you understand it.

This:

[NSDate date]

Returns the date that means now. It does not have a time zone. It is not in GMT or in any other time zone. It does not have one. Your code:

[NSDate dateWithTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT] sinceDate:[NSDate date]];

Means a time that isn't now for any user outside GMT. I'll repeat that: your NSDate doesn't describe now. It's like sitting in San Francisco, looking at your watch which is set in the correct local time and it saying 12:00 then telling everybody "that means it is 4AM because we're 8 hours behind GMT".

As a result:

[df stringFromDate:firstTime]

Will build a string that will show a time that isn't now.

Stop thinking you're smarter than everybody that's ever worked at Apple and try this:

NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"HH:mm:ss"];
[df setTimeZone:[NSTimeZone localTimeZone]];

NSString *secondTime = [df stringFromDate:[NSDate date]];
NSLog(@"%@", secondTime);

So that says "give me a string of 'now' in the local time zone". Tell me: does it output the correct thing?

One should let NSDate capture the real date/time, without trying to perform any timezone adjustment, and then let the NSDateFormatter format the string so that it's represented in the desired timezone.

So, looking at your code:

NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:@"HH:mm:ss"];
[df setTimeZone:[NSTimeZone localTimeZone]];

That's fine, though the setting of the timezone to the local timezone is unnecessary. Date formatters default to the current timezone.

But then you proceed to attempt to grab the current time, and adjust it:

NSDate *firstTime = [NSDate dateWithTimeInterval:[[NSTimeZone localTimeZone] secondsFromGMT] sinceDate:[NSDate date]];
NSLog(@"%@", firstTime);

While I understand why you attempted to do that, this is incorrect. No adjustment for timezone should be performed. So, that assignment of firstTime should be:

NSDate *firstTime = [NSDate date];
NSLog(@"%@", firstTime);

So, if you did this at 5:41pm (eastern), this NSLog will now report 2014-05-07 21:41:29 +0000 , but that's correct (because the +0000 indicates that it's showing you the time in UTC/GMT/Zulu).

Then, if you want to display that in the local timezone, you can take this un-adjusted [NSDate date] and use it with your formatter, like you did in your question:

NSString *secondTime = [df stringFromDate:firstTime];
NSLog(@"%@", secondTime);

That will then report 17:41:29 , like you expected it to.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM