views:

918

answers:

1

I know how to use NSTimeZone to derive the offset for the current time in another time zone. NSDate always returns relative to GMT, so how do I derive a string with the proper time zone information? i.e. I take the current time where I am (in EST) and using NSTimeZone end up subtracting the 3 hours necessary to represent the time in PST. But all I've done is subtract 3 hours from the time which is still represented relative to my time zone. How do I get NSDateFormatter to spit out the time using the destination time zone?

One tack I tried was:

NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];
NSTimeZone *tz = [NSTimeZone timeZoneForSecondsFromGMT:(-8 * 3600)]; // for PST
NSDateComponents *dc = [cal components: NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:now];
[cal setTimeZone:tz];
NSDate *newDate = [cal dateFromComponents:dc];

No love. I could take the individual date components and compose a string, but it wouldn't be localizable.

A related problem:

NSTimeZone *tz = [NSTimeZone timeZoneForSecondsFromGMT:(-8 * 3600)]; // for PST
NSString *abbreviation = [tz abbreviation];
NSString *name = [tz name];

Both abbreviation and name end up returning GMT-0800, not PST as I'd expect. So I couldn't even do the above if I wanted to. What am I doing wrong?

+1  A: 

NSDate always returns relative to GMT

This doesn't make sense. NSDate just encapsulates an absolute moment in time (let's forget about relativity for a second) and it has no concept of time zones whatsoever. To say that NSDate times are relative to GMT is wrong.

To output a date in a specific time zone, you should create an instance of NSDateFormatter and call setTimeZone: on it to set the time zone. According to the Unicode docs, the format string @"zzz" should output the time zone value as "PST".

Ole Begemann
The NSDateFormatter setTimeZone: method was the thing I overlooked. Thanks. I do realize how an NSDate works; what I meant was that NSDateFormatter (or description) always expressed the time in my time zone.The other issue still remains: NSDate *now = [NSDate date]; NSTimeZone *tz = [NSTimeZone timeZoneForSecondsFromGMT:-7*3600]; NSDateFormatter *df = [[NSDateFormatter alloc] init]; [df setDateFormat:@"'Updated' EEE MMM dd 'at' h:mm a zzz"]; [df setTimeZone:tz]; NSString *s = [df stringFromDate:now];Still yields: Updated Wed Mar 24 at 5:55 AM GMT-07:00
rsswtmr
Hm, perhaps NSDateFormatter only recognizes these time zone format specifiers when converting a date string to NSDate and not the other way around? The Unicode specs I linked to above seem to give implementers a lot of leeway on how to display time zone info if time zones names are not available. I really don't know how it works in detail. And googling doesn't uncover much, either.
Ole Begemann
I experimented a bit and found out that the format string `@"zzz"` will indeed output "PDT" (for today's date). However, this will only work if the time zone you set for the date formatter has been created with a name or an abbreviation instead of just the number of seconds from GMT: `[NSTimeZone timeZoneWithAbbreviation:@"PST"]`. I guess this makes sense since the system otherwise has no way of telling which specific time zone you mean. I also had to set the date formatter's locale to en-US explicitly.
Ole Begemann
Yeah, it was pointed out to me yesterday that GMT-05:00 could just as easily represent Peru Time or Columbia Time as well as Eastern Standard Time. Again, don't know why that didn't occur to me. The only time zone information I get from our servers is hours offset from GMT, so I guess we'll have to forego the nice time zone description. Thanks for your help.
rsswtmr