0
votes

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

2
those could be the same time... the first time outputs a timezone the second doesn'tGrady Player
Well, you corrupted the time in the NSDate object. Since you derived the date string from the NSDate object, it would be corrupted too.Hot Licks
(Hint: Don't try to "correct" the timezone of an NSDate. It is automatically in GMT.)Hot Licks
[dateTime description] and hence NSLog, always report the time as GMT. It looks to me as if everything is working exactly as expected (assuming your timezone is GMT-4, EDT)David Berry
Hello. In what way did I "corrupt" the NSDate object? I am trying to get the NSString of the same date that is displayed after FIRST TIME:. If I do not change the NSTimeZone when I create firstTime it will appear in the GMT time. All I want to do is get the exact output I got from NSLogging firstTime into an NSString so when I output that NSString, it will be identical. Also, I see someone posted that NSDateFormatter by default has the timezone set to local time zone and that explicitly setting it is redundant. Is that true? I don't see his post anymore.user3614030

2 Answers

3
votes

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.

2
votes

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?