我正在寻找正确的方法来获取给定地点/时区的实际日期和时间,并能够将其与同一地点的给定日期/时间进行比较。
让我们说,例如,巴黎,即GMT +1。就像我们现在一样,由于夏令时,巴黎也可以是GMT + 2,但据我所知,这是一个例外的一部分因此必须考虑到答案,但不能作为一般参数。这里的重要词汇是“给定的地方”。
所以,如果我想知道它在Sidney Australia或Paris France的日期和时间,并将该日期纳入NSDate,以便能够将其与另一个同时代表另一个日期/时间的NSDate进行比较地方,我该怎么办?
我已经阅读了一些问题和答案的页面和页面,其中包含评论,甚至是已接受的答案,这些来自经验丰富的用户:不是一个好的答案-1,错误的,不是正确的做法,绝对错误,... 。
那么,你知道这样做的正确方法吗?
在一个完美的世界中,即使用户的手机没有处于良好的时间和/或日期和/或时区,或者任何可以接近完美的任何东西而不需要连接到那个日期/时间,该日期/时间也是绝对的日期/时间服务器。
答案 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);
但是,据我所知和测试,那天/时间不可能是绝对的。它基于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