我住在美国东部时区(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秒。 daylightOffset为0.如何正确获取用户所在时区的日光偏移? NSDateFormatter正确地解析了日期,所以它必须知道NSTimeZone没有告诉我的东西。
谢谢!
答案 0 :(得分:5)
[localTime secondsFromGMT]
返回真正的GMT,包括夏令时,您可以通过[localTime daylightSavingTimeOffset]
答案 1 :(得分:1)
这似乎是recurring problem for many(me included),在我的头发拉得太久之后我终于解决了这个问题
此代码所依赖的假设是:
为了实现1.我使用初始化为Gregorian,GMT的唯一NSCalendar实例 这也是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]] ;
}
希望这有助于某人!
答案 2 :(得分: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);