iOS在未来创builddate忽略夏令时

我正在努力与date和date创builddate,但夏令时不断阻碍和混乱了我的时代。

这里是我的代码移动到下个月的第一天的午夜为一个date:

+ (NSDate *)firstDayOfNextMonthForDate:(NSDate*)date { NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; calendar.timeZone = [NSTimeZone systemTimeZone]; calendar.locale = [NSLocale currentLocale]; NSDate *currentDate = [NSDate dateByAddingMonths:1 toDate:date]; NSDateComponents *components = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:currentDate]; [components setDay:1]; [components setHour:0]; [components setMinute:0]; [components setSecond:0]; return [calendar dateFromComponents:components]; } + (NSDate *) dateByAddingMonths: (NSInteger) monthsToAdd toDate:(NSDate*)date { NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; calendar.timeZone = [NSTimeZone systemTimeZone]; calendar.locale = [NSLocale currentLocale]; NSDateComponents * months = [[NSDateComponents alloc] init]; [months setMonth: monthsToAdd]; return [calendar dateByAddingComponents: months toDate: date options: 0]; } 

当我在一个date迭代运行方法时,给出了date:

 2013-02-01 00:00:00 +0000 2013-03-01 00:00:00 +0000 2013-03-31 23:00:00 +0000 should be 2013-04-01 00:00:00 +0000 2013-04-30 23:00:00 +0000 should be 2013-05-01 00:00:00 +0000 

我最初的想法是不使用systemTimeZone但似乎没有什么区别。 任何想法,我可以如何使时间不变,不考虑夏令时的变化?

对于给定的日历date/时间,作为一般规则来预测代表什么实际时间(自纪元以来的秒数)是不可能的。 时区更改和DST规则更改。 这是生活中的事实。 夏令时在澳大利亚有一个折磨的历史。 DST规则在以色列非常不可预测。 DST规则最近在美国发生了变化,给正在存储秒数而不是日历date的微软带来了巨大的麻烦。

从来没有NSDateComponents保存NSDate 。 如果你的意思是“2013年5月在伦敦的第一个”,那么在你的数据库中保存“2013年5月的第一个伦敦”。 然后计算一个尽可能接近实际事件的NSDate 。 如果你关心日历事情( NSDateComponents ,使用NSDateComponents做所有的日历math运算。 只有NSDatemath,如果你真的只关心秒。

编辑:对于很多非常有用的背景,请参阅date和时间编程指南 。

还有一个关于日历组件的说明:当我说“2013年5月的第一个伦敦”时,并不意味着“五月一号午夜”。 不要添加日历组件,你实际上并不意味着。

请记住,您的程序打印到日志的是GMT时间,而不是当地时间。 因此,在当地时区切换到夏令时之后的date格林尼治标准时间将会移动一个小时,这是正确的。

我有同样的问题,人们说这不是一个真正的问题(正如我在一些相关的线程中看到的)不利于这种情况。 无论何时需要处理时区和DST,这种问题都会让人感到痛苦,而且我总是觉得每次都要重新学习。

我正在尽可能地处理新纪元(这是一个图表应用程序),但有时候我需要使用NSDate和NSCalendar(即格式化轴标签,并标记日历月,季度和年)。 我为此奋斗了一天左右,试图在日历等设置不同的时区。

最后,我发现我的应用程序委托中的以下代码行非常有帮助:

 // prevent DST bugs by setting default timezone for app if let utcZone = NSTimeZone(abbreviation: "UTC") { NSTimeZone.setDefaultTimeZone(utcZone) } 

最重要的是,源数据必须进行消毒处理,所以每当我在传入数据上使用NSDateFormatter时,我都确保将数据源的时区设置为正确的时区(在我的情况下是GMT)。 这消除了数据源中令人讨厌的DST问题,并确保所有NSDate都可以很好地转换成时代,而不用担心DST。