6

This code

NSCalendar *calendar =[NSCalendar currentCalendar];
[gregorian setTimeZone:tz];

NSLog(@"%@", [gregorian timeZone]);

NSDateComponents *comp = [gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit) fromDate:[NSDate date]];

[comp setDay:info.day];
[comp setMonth:info.month];
[comp setYear:info.year];
[comp setHour:info.hour];
[comp setMinute:info.minute];
[comp setSecond:info.second];
[comp setTimeZone:tz];  

NSLog(@"%@", [comp timeZone]);
NSLog(@"%@", [gregorian dateFromComponents:comp]);

shows the following in console:

Europe/Moscow (MSKS) offset 14400 (Daylight)

Europe/Moscow (MSKS) offset 14400 (Daylight)

2011-08-31 20:00:00 +0000

So, the timezone for calendar and components is specified correctly, but [gregorian dateFromComponents:comp] returns NSDate value with wrong time zone (GMT).

What do I need to correct to get proper timezone?

Mitry
  • 375
  • 4
  • 13
  • 2
    If you NSLog a `NSDate`object directly, you will always get its GMT representation. Anyway, `NSDate` objects have no concept of timezones whatsoever. They represent an **absolute** instant in time measured from a reference date. You can get different human readable *representations* of the date for the different timezones using a `NSDateFormatter`, but they that, representations. – albertamg Sep 06 '11 at 20:46
  • I think that NSDate hides the timezone from which it was derived in the insignificant bits of the timestamp. This is only intended to be used for [NSDate description], though, and is unreliable at best. – Hot Licks Sep 06 '11 at 20:52
  • Yeah, you are right, guys. Thanks, now I get it:) – Mitry Sep 06 '11 at 21:01
  • NSDate is the number of seconds since the first instant of 1/1/2001, GMT. Note the time zone. The description method uses the curet time zone of the user so it not the true NSDate but makes people happy in the representation. – zaph Sep 06 '11 at 21:09

2 Answers2

6

The output you are seeing is perfectly normal. If you NSLog a NSDate object directly, you will get whatever the description method returns, which is the GMT representation of the date (but that is not carved in stone).

NSDate objects are not subject to timezones. A NSDate represents an absolute instant in time measured from a reference date. For example, at the time of writing, the current date is something like 337035053.199801 (seconds since reference date), which can be represented as 2011-09-06 20:50:53 GMT or 2011-09-06 22:50:53 CEST. Both are different human readable representations of the same date.

In conclusion, what do you need to get the proper timezone? You need to use NSDateFormatter to get a string representation of your NSDate in any timezone you like.

albertamg
  • 28,492
  • 6
  • 64
  • 71
  • 1
    The reference date is in fact the first instant of 1 January 2001, GMT. Anyway, this represents the point in time when we start to count, i.e. `0.0` and you could *express* that point in time using any timezone. – albertamg Sep 06 '11 at 22:29
  • And a place in space, specifically a timezone. – zaph Sep 07 '11 at 10:42
  • 1
    `NSDate`s are not subject to GMT or any other timezone for that matter (yes, internally they store a delta from a reference date *expressed* in GMT). It's wrong to [try to convert a date into another time zone by manipulating the original date and deriving a different date object](http://stackoverflow.com/questions/2503397/nsdate-expressed-in-different-time-zones-i-e-local-time-zone-gmt-400-to-pst). A `NSDate` represents an invariant point in time and it does not depend on what part of the world you are. There is just one NSDate that represents *now*, not multiple NSDates for every timezone. – albertamg Sep 07 '11 at 14:44
  • From the Apple documentation: 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. – zaph Sep 07 '11 at 15:13
  • 1
    As I said, yes, internally they store a delta from a reference date expressed in GMT. My point is that dates are not relative to timezones. Things such as `- (NSDate*) convertToUTC:(NSDate*)sourceDate;`, which I've seen, are nonsense. – albertamg Sep 07 '11 at 15:15
1

This question comes up quite often and the answer is to use an NSDateFormatter to get the desired output for the date format. Currently it is always printed with the GMT timezone. Here is the discussion for the documentation for NSDate:

Discussion
The representation is not guaranteed to remain constant across different releases of the operating system. To format a date, you should use a date formatter object instead (see NSDateFormatter and Data Formatting Guide)

Joe
  • 56,979
  • 9
  • 128
  • 135