iPhone - Correct way for getting current date and time for a given place / timezone and compare it with another date/time in the same place iPhone - Correct way for getting current date and time for a given place / timezone and compare it with another date/time in the same place ios ios

iPhone - Correct way for getting current date and time for a given place / timezone and compare it with another date/time in the same place


I'm searching the correct way to get the actual date and time for a given place / timezone.

[NSDate date]returns a date object representing the current date and time, no matter where you are. NSDates are not subject to places or time zones. There is just one NSDate that represents now or any other moment for that matter, not different date objects for every time timezone. Therefore, you should not attempt to convert a date between time zones.

NSDate objects represent an absolute instant in time. Consider the following example of how two date representations in different time zones (9/9/11 3:54 PM in Paris and 9/9/11 11:54 PM in Sydney) are actually the same date.

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];[formatter setDateStyle:NSDateFormatterShortStyle];[formatter setTimeStyle:NSDateFormatterShortStyle];[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Paris"]];NSDate *aDate = [formatter dateFromString:@"9/9/11 3:54 PM"];[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Australia/Sydney"]];NSDate *anotherDate = [formatter dateFromString:@"9/9/11 11:54 PM"];NSLog(@"%@",anotherDate);if ([aDate isEqualToDate:anotherDate]) {    NSLog(@"How about that?");}

It logs that last message because 9/9/11 3:54 PM in Paris and 9/9/11 11:54 PM in Sydney are actually the same instant in time. When it is 9/9/11 3:54 PM in Paris, it is 9/9/11 11:54 PM in Sydney.

both gives in the debugger and NSLog 2011-09-09 14:26:02, but it's now 16:26 so I guess it should return 16:26:02 +0200

When it comes to output a date, bear in mind that NSDate's description method returns time in GMT and you need to use a NSDateFormatter to create a date string representing the local time in Paris, Sydney, etc. from a date:

NSDate *now = [NSDate date];NSDateFormatter *formatter = [[NSDateFormatter alloc] init];[formatter setDateStyle:NSDateFormatterShortStyle];[formatter setTimeStyle:NSDateFormatterShortStyle];[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Australia/Sydney"]];NSLog(@"%@",[formatter stringFromDate:now]); //--> 9/9/11 11:54 PM[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Paris"]];NSLog(@"%@",[formatter stringFromDate:now]); //-->  9/9/11 3:54 PM

ok, but if I want to know if that time is after 15:00, how may I test that ?

Create an NSDate object that represents today at 15:00 (local time) and compare it to "now":

NSDate *now = [NSDate date];NSCalendar* myCalendar = [NSCalendar currentCalendar];NSDateComponents* components = [myCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit                                              fromDate:[NSDate date]];[components setHour: 15];[components setMinute: 0];[components setSecond: 0];NSDate *todayAt15 = [myCalendar dateFromComponents:components];if ([now compare:todayAt15] == NSOrderedDescending) {    NSLog(@"After 15:00 local time");}

It turns out @Oliver needed to check if it is after 15:00 in Paris so he needed to create a date that represents today at 15:00 Paris time (not local time). For an example on how to do that, see @Oliver's answer. Just to be clear, my third snippet of code shows how to check if it is after 15:00 local time.


After a big headache and starting to understand what NSDate is, I imagined that kind of solution. What do you think about that way of doing ?

// Now, an absolute date and time that represent now all around the world, that is made to play withNSDate *now = [NSDate date];// A specific calendar for a specific place in the worldNSCalendar* parisCalendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];[parisCalendar setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Paris"]];// Now components seen from ParisNSDateComponents* componentsNowInParis = [parisCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit|NSTimeZoneCalendarUnit fromDate:now];// Tricking a copy of "Now components seen from Paris" to force 15:00:00, in ParisNSDateComponents* componentsInParisAt15 = [[componentsNowInParis copy] autorelease];[componentsInParisAt15 setHour:15];[componentsInParisAt15 setMinute:0];[componentsInParisAt15 setSecond:0];// Getting an universal date reference that represent what could be 15:00:00 seen from paris, Or 19:00:00 from GMT+4NSDate* dateAt15 = [parisCalendar dateFromComponents:componentsInParisAt15];// We now have two universal dates that can be compared each other// If "now" is 16:00:00, those date will show a 60 minutes difference all around the worldNSLog(@"%@", now);NSLog(@"%@", dateAt15);

Some reference : http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DatesAndTimes/Articles/dtTimeZones.html#//apple_ref/doc/uid/20000185-SW4

But, as far as I know and tested, that day/time cannot be really absolute. It is based on the iPhone date/time/timezone, that can be wrong.


Use NSCalendar, and the setTimeZone method.

NSDate *newDate;NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:~ NSTimeZoneCalendarUnit fromDate:[NSDate date]];newDate = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];NSLog(@"newDate: %@", newDate);NSLog(@"newDate: %.0f", [newDate timeIntervalSinceReferenceDate]);

newDate: 2011-09-09 15:02:09 +0000
newDate: 337273330

[dateComponents setTimeZone:[NSTimeZone timeZoneWithName:@"Australia/Sydney"]];newDate = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];NSLog(@"newDate: %@", newDate);NSLog(@"newDate: %.0f", [newDate timeIntervalSinceReferenceDate]);

newDate: 2011-09-09 00:52:03 +0000
newTimeInterval: 337222930

[dateComponents setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Paris"]];newDate = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];NSLog(@"newDate: %@", newDate);NSLog(@"newDate: %.0f", [newDate timeIntervalSinceReferenceDate]);

newDate: 2011-09-09 08:52:03 +0000
newTimeInterval: 337251730