iPhone - 获取给定地点/时区的当前日期和时间的正确方法,并将其与同一地点的其他日期/时间进行比较

时间:2011-09-09 13:16:25

标签: iphone ios cocoa-touch datetime timezone

我正在寻找正确的方法来获取给定地点/时区的实际日期和时间,并能够将其与同一地点的给定日期/时间进行比较。

让我们说,例如,巴黎,即GMT +1。就像我们现在一样,由于夏令时,巴黎也可以是GMT + 2,但据我所知,这是一个例外的一部分因此必须考虑到答案,但不能作为一般参数。这里的重要词汇是“给定的地方”。

所以,如果我想知道它在Sidney Australia或Paris France的日期和时间,并将该日期纳入NSDate,以便能够将其与另一个同时代表另一个日期/时间的NSDate进行比较地方,我该怎么办?

我已经阅读了一些问题和答案的页面和页面,其中包含评论,甚至是已接受的答案,这些来自经验丰富的用户:不是一个好的答案-1,错误的,不是正确的做法,绝对错误,... 。

那么,你知道这样做的正确方法吗?

在一个完美的世界中,即使用户的手机没有处于良好的时间和/或日期和/或时区,或者任何可以接近完美的任何东西而不需要连接到那个日期/时间,该日期/时间也是绝对的日期/时间服务器。

3 个答案:

答案 0 :(得分:34)

  

我正在寻找正确的方法来获取给定地点/时区的实际日期和时间。

[NSDate date]返回一个代表当前日期和时间的日期对象,无论在哪里NSDate不受地点或时区限制。只有一个NSDate代表现在或任何其他时刻,而不是每个时区的不同日期对象。因此,您不应尝试在时区之间转换日期。

NSDate个对象代表绝对即时。请考虑以下示例,了解两个日期表示在不同时区(巴黎的9/9/11 3:54 PM和悉尼的9/9/11 11:54 PM)实际上是相同的日期。

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?");
}

它记录了最后一条消息,因为巴黎的9/9/11 3:54 PM和悉尼的9/9/11 11:54 PM实际上是同一时刻。当它在巴黎9/9/11 3:54 PM时,在悉尼是9/9/11 11:54 PM

  

两者都在调试器和NSLog 2011-09-09 14:26:02中给出,但它现在是16:26所以我猜它应该返回16:26:02 +0200

在输出日期时,请记住NSDate的{​​{1}}方法在GMT中返回时间,您需要使用description来创建表示日期的日期字符串当地时间在巴黎,悉尼等地的日期:

NSDateFormatter

  好的,但如果我想知道这个时间是否在15:00之后,我该怎么测试呢?

创建一个今天15:00(当地时间)代表的NSDate对象,并将其与“now”进行比较:

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

事实证明@Oliver需要在巴黎15:00之后检查它是否所以他需要创建一个代表今天巴黎时间15:00(不是当地时间)的日期。有关如何执行此操作的示例,请参阅@ Oliver的答案。为了清楚起见,我的第三段代码显示了如何检查它是否在当地时间15:00之后。

答案 1 :(得分:12)

经过一番头痛并开始明白NSDate是什么,我想到了那种解决方案。您如何看待这种做法?

// Now, an absolute date and time that represent now all around the world, that is made to play with
NSDate *now = [NSDate date];

// A specific calendar for a specific place in the world
NSCalendar* parisCalendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
[parisCalendar setTimeZone:[NSTimeZone timeZoneWithName:@"Europe/Paris"]];

// Now components seen from Paris
NSDateComponents* 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 Paris
NSDateComponents* 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+4
NSDate* 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 world
NSLog(@"%@", now);
NSLog(@"%@", dateAt15);

一些参考:http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/DatesAndTimes/Articles/dtTimeZones.html#//apple_ref/doc/uid/20000185-SW4

但是,据我所知和测试,那天/时间不可能是绝对的。它基于iPhone日期/时间/时区,这可能是错误的。

答案 2 :(得分:9)

使用NSCalendar和setTimeZone方法。

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
新日期: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