1

我住在美国东部时区 (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 没有告诉我的一些事情。

谢谢!

4

3 回答 3

5

[localTime secondsFromGMT]返回包括夏令时在内的真实 GMT,您可以通过以下方式获得偏移量本身[localTime daylightSavingTimeOffset]

于 2013-03-17T08:21:47.553 回答
1

对于许多人包括我)来说,这似乎是一个反复出现的 问题 ,并且在将头发拉得太长之后,我终于解决了这个问题。

此代码所依赖的假设是:

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

希望这对某人有帮助!

于 2013-03-23T14:53:24.597 回答
0

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

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);
于 2012-07-23T03:41:14.340 回答