首页 文章

NSDateComponents组件:fromDate和Time Zones

提问于
浏览
11

我有一种方法,通过将其分解为NSDateComponents,将小时和第二组分从NSDate中提取出来 . 我的代码如下......

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]];

我的问题是我在转换中损失了一个小时 . 我怀疑它是由时区引起的,但据我所知,日期传入和使用的日历都是GMT .

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

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

我希望我能获得8小时和0分钟,但实际上我的工作时间是7小时 .

我的系统时间是GMT,因此上面的NSDate目前是英国夏令时的0100 .

3 回答

  • 5

    问题是,GMT不等于英国夏令时 . 日期 2010-08-02 08:00:00 +0100 等于 2010-08-02 07:00:00 GMT 所以7小时是你应该得到的结果 .

  • 15

    另请注意, 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

    我同意aqua . 这是非常误导,并让我几天撞到屏幕上 . 它的工作方式如下:[NSDate date]始终返回当前日期 . 所以在上面的例子中它将是2010-08-02 08:00:00 . 当我们转换为NSDateComponents时,实际时间会丢失并转换为一组不再占用时区的整数(小时,年等) .

    当转换回NSDate对象时,它将采用年,月,日等的值并相对于GMT给你,因此丢失了一小时 . 这就是它在框架中决定的方式 . 我所做的是以下内容:

    +(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 .

相关问题