代码之家  ›  专栏  ›  技术社区  ›  mmccomb

NSC组件omponents:fromDate and 时区

  •  11
  • mmccomb  · 技术社区  · 14 年前

    unsigned hourAndMinuteFlags = NSHourCalendarUnit | NSMinuteCalendarUnit;
    NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    [calendar setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
    NSDateComponents* travelDateTimeComponents = [calendar components:hourAndMinuteFlags fromDate:travelDate];
    NSString* hours = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents hour]];
    NSString* minutes = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents minute]];
    

    我的问题是我在转换过程中损失了一个小时。我有一个怀疑,这是由于时区,但就我所能看到的日期正在通过和日历正在使用的都是格林威治时间。

    例如,如果我传入以下NSDate对象(这是一个日志[NSDate description])。。。

    2010-08-02 08:00:00 +0100
    

    我的系统时间是格林威治标准时间,因此上面的NSDate现在是英国夏季时间+0100。

    3 回复  |  直到 14 年前
        1
  •  5
  •   Ole Begemann    14 年前

    问题是,格林威治时间不等于英国夏季时间。日期 2010-08-02 08:00:00 +0100 2010-08-02 07:00:00 GMT 所以7小时是你应该期待的结果。

        2
  •  15
  •   aqua    14 年前

    还要记住 NSDate 对象总是根据GMT显示时间,而从该日期提取的组件会被 timeZoneWithName

    NSDate *today = [NSDate date];
    NSLog(@"Today's date: %@",today);
    
    unsigned hourAndMinuteFlags = NSHourCalendarUnit | NSMinuteCalendarUnit;
    NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    [calendar setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
    NSDateComponents* travelDateTimeComponents = [calendar components:hourAndMinuteFlags fromDate:today];
    NSString* hours = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents hour]];
    NSString* minutes = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents minute]];
    
    NSLog(@"Calendar: %@",calendar);
    NSLog(@"Travel Components: %@",travelDateTimeComponents);
    NSLog(@"Hours: %@",hours);
    NSLog(@"Minutes: %@",minutes);
    

    [Session started at 2011-01-23 12:59:17 -0700.]
    2011-01-23 12:59:19.755 testttt[5697:207] Today's date: 2011-01-23 19:59:19 +0000
    2011-01-23 12:59:19.756 testttt[5697:207] Calendar: <__NSCFCalendar: 0x4b2ca70>
    2011-01-23 12:59:19.757 testttt[5697:207] Travel Components: <NSDateComponents: 0x4b2de20>
    2011-01-23 12:59:19.757 testttt[5697:207] Hours: 19
    2011-01-23 12:59:19.758 testttt[5697:207] Minutes: 59
    

    现在如果我们改变时区。。。

    NSDate *today = [NSDate date];
    NSLog(@"Today's date: %@",today);
    
    unsigned hourAndMinuteFlags = NSHourCalendarUnit | NSMinuteCalendarUnit;
    NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    [calendar setTimeZone:[NSTimeZone timeZoneWithName:@"MST"]];
    NSDateComponents* travelDateTimeComponents = [calendar components:hourAndMinuteFlags fromDate:today];
    NSString* hours = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents hour]];
    NSString* minutes = [NSString stringWithFormat:@"%02i", [travelDateTimeComponents minute]];
    
    NSLog(@"Calendar: %@",calendar);
    NSLog(@"Travel Components: %@",travelDateTimeComponents);
    NSLog(@"Hours: %@",hours);
    NSLog(@"Minutes: %@",minutes);
    

    输出:

    2011-01-23 13:05:29.896 testttt[5723:207] Today's date: 2011-01-23 20:05:29 +0000
    2011-01-23 13:05:29.897 testttt[5723:207] Calendar: <__NSCFCalendar: 0x4e10020>
    2011-01-23 13:05:29.897 testttt[5723:207] Travel Components: <NSDateComponents: 0x4e0f6d0>
    2011-01-23 13:05:29.898 testttt[5723:207] Hours: 13
    2011-01-23 13:05:29.898 testttt[5723:207] Minutes: 05
    

    注意当地时间和分钟是如何变化的,但是“今天的日期:”部分仍然反映了GMT。如果你问我的话,对程序员来说有点误导。

        3
  •  4
  •   Michael M    13 年前

    +(NSDateComponents *)getComponentFromDate:(NSDate *)date {
    
        NSCalendar * gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    
        unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSWeekdayCalendarUnit | NSDayCalendarUnit;
        NSDateComponents* components = [gregorian components:unitFlags fromDate:date];
    
        NSTimeZone* timeZone = [NSTimeZone localTimeZone];
        if(timeZone.isDaylightSavingTime) components.hour = ((int)timeZone.daylightSavingTimeOffset/3600);
    
        [gregorian release];
    
        return components;
    }
    

    这将给我一个四舍五入到当前日期的组件的“更正”版本,当传递到日历以检索日期时,它将始终设置为作为参数传递的日期当天的00:00:00。