我正在寻找正确的方法来获得给定地点/时区的实际日期和时间,并能够将其与同一地点的给定日期/时间进行比较。
以巴黎为例,它是GMT +1。就像我们现在一样,巴黎也可以是GMT+2,因为夏时制,但据我所知,这是例外的一部分,所以必须考虑到答案,但不能作为一般参数。这里重要的词是"given place"。
如果我想知道它在澳大利亚悉尼或法国巴黎的日期和时间,并将那个日期放入NSDate以便能够将它与另一个NSDate进行比较那将代表同一地点的另一个日期/时间,我该怎么做?
我读了一页又一页的带有评论的问题和答案,甚至是在公认的答案上,有经验的用户说:不是一个好的答案-1,错误的,不是正确的方法,绝对错误的,…
那么,你知道正确的真正方法吗?
在一个完美的世界里,这个日期/时间将是绝对的,即使用户的手机不在正确的时间和/或日期和/或时区,或者任何可以接近完美的东西,而不需要连接到日期/时间服务器。
我正在寻找正确的方法来获得给定地点/时区的实际日期和时间。
[NSDate date]
返回一个表示当前日期和时间的日期对象,无论在的位置。NSDate
不受地点或时区的限制。只有一个NSDate表示now或任何其他时刻,而不是每个时间时区的不同日期对象。因此,您不应该尝试在时区之间转换日期。
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
的description
方法返回GMT时间,您需要使用NSDateFormatter
从日期创建一个表示巴黎,悉尼等当地时间的日期字符串:
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
好的,但是如果我想知道那个时间是否在15:00之后,我该如何测试呢?
创建一个表示今天15:00(当地时间)的NSDate对象,并将其与"现在"进行比较:
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");
}
结果@Oliver需要检查巴黎时间是否在15:00之后所以他需要创建一个代表今天巴黎时间15:00(不是当地时间)的日期。有关如何做到这一点的示例,请参阅@Oliver的回答。为了清楚起见,我的第三段代码展示了如何检查它是否在当地时间15:00之后。
在开始理解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的日期/时间/时区,这可能是错误的。
使用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
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