首页 文章

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

提问于
浏览
17

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

让我们说,例如,巴黎,也就是格林尼治标准时间1.正如我们现在所说的那样,由于夏令时,巴黎也可以是格林威治标准时间2,但据我所知,它是例外的一部分因此必须考虑到答案,但不作为一般的参数 . 这里重要的词是“给定的地方” .

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

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

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

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

3 回答

  • 34

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

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

    NSDate 对象表示 absolute 及时 . 请考虑以下示例,说明不同时区(巴黎的 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

    在输出日期时,请记住 NSDatedescription 方法在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对象,并将其与“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");
    }
    

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

  • 9

    经过一番头痛并开始了解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日期/时间/时区,这可能是错误的 .

  • 12

    使用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

相关问题