I have a method which extracts the hour and second components form a NSDate by breaking it down into its NSDateComponents. My code is as follows...
unsigned hourAndMinuteFlags = NSHourCalendarUnit | NSMinuteCalendarUnit;
NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
NSDateComponents* travelDateTimeComponents = [calendar components:hourAndMinuteFlags fromDate:travelDate];
NSString* hours = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents hour]];
NSString* minutes = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents minute]];
My problem is that I'm losing an hour in the conversion. I have a suspicion that it's due to timezones but as far as I can see both the date being passed in and the calendar being used are both GMT.
For example if I pass in the following NSDate object (this is a log of [NSDate description])...
2010-08-02 08:00:00 +0100
I expect that I get 8 for hours and 0 for minutes, but I actually get back 7 for my hours.
My system time is GMT, hence the NSDate above is currently +0100 for British Summer Time.
The thing is, GMT is not equal to British Summer Time. The date
2010-08-02 08:00:00 +0100
is equal to2010-08-02 07:00:00 GMT
so 7 hours is the result you should expect.Also keep in mind that the
NSDate
object always shows time according to GMT, whereas the components you're pulling from that date are altered by thetimeZoneWithName
part.Example:
Console Output:
Now if we change the Time Zone...
Output:
Notice how the local hours and minutes change, but the "Today's date:" part still reflects GMT. A bit misleading to programmers, if you ask me.
I agree with aqua. It is very misleading and has led me to days hitting my head against the screen. It works like this: [NSDate date] always returns current date. So in the example above it will be 2010-08-02 08:00:00. When we convert into NSDateComponents, the actual time is lost and converted into a set of integers (hour, year etc.) which no longer hold the Time Zone.
When converting back to a NSDate object it will take the values of year, month, day etc. and give it to you relative to GMT, hence the hour lost. It's just the way it was decided in the framework. What I do is the following:
That will give me a 'corrected' version of the components rounded to the current day which when passed to the calendar to retrieve a date will always be set to 00:00:00 on the day of the date passed as argument.