【问题标题】:iPhone4 iOS5 [[NSTimeZone localTimeZone] daylightSavingTimeOffset] wrong for daylight savings time?iPhone4 iOS5 [[NSTimeZone localTimeZone] calendarSavingTimeOffset] 夏时制错误?
【发布时间】:2011-12-25 16:06:10
【问题描述】:

我住在美国东部时区 (EST),几周前夏令时开始了。我正在测试我早期的一些代码,这些代码(据说)运行良好,并注意到天秒计算提前 1 小时运行。

这是我用于测试的代码:

 int  gmtOffset =  [[NSTimeZone localTimeZone] secondsFromGMT];
 int daylightOffset =  [[NSTimeZone localTimeZone] daylightSavingTimeOffset];

  int daySeconds =  ((int)([date timeIntervalSinceReferenceDate]+gmtOffset+daylightOffset))%(86400+1);

 NSLog(@"Day seconds: %i", daySeconds);

结果比预期值少 3600 秒。日光偏移为 0。如何正确获取用户所在时区的日光偏移? NSDateFormatter 正确解析日期,所以它必须知道 NSTimeZone 没有告诉我的一些事情。

谢谢!

【问题讨论】:

    标签: ios5 nsdate dst iphone-4 nstimezone


    【解决方案1】:

    [localTime secondsFromGMT] 返回真正的 GMT,包括夏令时,您可以通过 [localTime daylightSavingTimeOffset] 获取偏移量本身

    【讨论】:

      【解决方案2】:

      这似乎是recurring problem for many (me included),在拉了我的头发太久之后,我终于解决了这个问题。

      此代码所依赖的假设是:

      1. 你感兴趣的是日期,而不是时间
      2. 您希望您的日期计算忽略任何夏令时
      3. 您需要一个足够简单的日期字符串表示,以便您可以持久保存它。

      为了实现 1. 我使用了唯一的 NSCalendar 实例,该实例初始化为 Gregorian, GMT 这也适用于 2。

      对于 3. NSDateFormatter 使用唯一的日历其时区进行初始化。 将格式化程序的时区设置为用于计算的日历的时区是我遇到的所有问题的关键!

      这应该总是正确的(假设下面的代码是DateModel 类的一部分):

      NSDate * today = [DateModel normalize: [NSDate date]] ;
      NSString*todayS= [DateModel dateToString: today] ;
      BOOL alwaysTrue=[[DateModel normalize: [NSDate date]] isEqual: [DateModel stringToDate: todayS]] ; 
      

      代码如下:

      + (NSDate *) normalize: (NSDate *) date {
          NSDateComponents * comps = [[DateModel calendar] components:NSYearCalendarUnit
                                                                  |   NSMonthCalendarUnit
                                                                  |   NSDayCalendarUnit
                                                                  |   NSHourCalendarUnit
                                                                  |   NSMinuteCalendarUnit
                                                                  |   NSSecondCalendarUnit
                                                             fromDate:date] ;
      
          [comps setHour:0] ;
          [comps setMinute:0] ;
          [comps setSecond:0] ;
      
          NSDate * dateOnly = [[DateModel calendar] dateFromComponents:comps] ;
      
          return dateOnly ;
      }
      
      + (NSCalendar *) calendar {
          static NSCalendar * calendar = nil ;
          if (calendar == nil) {
              calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] ;
              calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"GMT"] ;
          }
          return calendar ;
      }
      
      + (NSDateFormatter *) dateFormatter {
          static NSDateFormatter * formatter = nil ;
          if (formatter == nil) {
              formatter = [[NSDateFormatter alloc] init] ;
              [formatter setCalendar:[self calendar]] ;          // <- This is
              [formatter setTimeZone:[self calendar].timeZone] ; // <- critical
              [formatter setDateFormat:@"yyyyMMdd"] ;
          }
          return formatter ;
      }
      
      + (NSDate *) dateFromString: (NSString *) stringDate {
          return [DateModel normalize: [[DateModel dateFormatter] dateFromString:stringDate]] ;
      }
      
      + (NSString *) stringFromDate: (NSDate *) date {
          return [[DateModel dateFormatter] stringFromDate:[DateModel normalize: date]] ;
      }
      

      希望这对某人有所帮助!

      【讨论】:

        【解决方案3】:

        如果要确定自午夜以来的秒数,可以使用日期组件。此代码针对夏令时进行了适当调整。

        NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
        [calendar setTimeZone:[NSTimeZone localTimeZone]];
        
        NSDateComponents *comps = [calendar components:NSHourCalendarUnit|NSMinuteCalendarUnit| NSSecondCalendarUnit
                                              fromDate:[NSDate date]];
        NSInteger time = [comps hour] * 3600 + [comps minute] * 60 + [comps second];
        
        NSLog(@"Day seconds: %i", time);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-04
          • 1970-01-01
          • 1970-01-01
          • 2012-11-25
          • 2014-04-26
          • 1970-01-01
          相关资源
          最近更新 更多