我正在尝试使用日期并在将来创建日期,但夏令时不断妨碍我的工作时间。
这是我的代码,可以移动到下个月第一天的午夜约会:
+ (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];
}
给出了日期迭代地运行方法的日期:
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
,但这似乎没有什么区别。关于如何使时间保持恒定而不考虑夏令时变化的任何想法?
答案 0 :(得分:7)
对于给定的日历日期/时间,通常不可能预测表示的实际时间(自纪元以来的秒数)。时区更改,DST规则更改。这是生活中的事实。夏令时在澳大利亚历史悠久。 DST规则在以色列非常难以预测。 DST规则最近在美国发生了变化,给微软带来了巨大的麻烦,因为微软存储的是秒而不是日历日期。
当您的意思是NSDate
时,永远不要保存NSDateComponents
。如果您的意思是“2013年5月1日在伦敦”,那么请在您的数据库中保存“2013年5月1日在伦敦”。然后计算出NSDate
,尽可能接近实际事件。如果您关心日历事物(如月份),请使用NSDateComponents
完成所有日历数学运算。如果你真的只关心秒钟,那么只做NSDate
数学。
编辑:对于许多非常有用的背景,请参阅Date and Time Programming Guide。
还有一个关于日历组件的旁注:当我说“2013年5月1日在伦敦”时,这并不意味着“5月1日午夜”。不要添加您实际上并不意味着的日历组件。
答案 1 :(得分:3)
请记住,您的程序打印到日志的是GMT时间,而不是您当地的时间。因此,在当地时区切换到夏令时之后的日期,GMT将移动一小时是正确的。
答案 2 :(得分:2)
我遇到了同样的问题,人们说这不是一个问题(正如我在一些相关主题上看到的那样)并不能帮助解决问题。无论何时你必须处理时区和夏令时,这种问题都会受到伤害,我总觉得每次都必须重新学习它。
我正在尽可能多地处理纪元时代(它是一个图表应用程序),但有时我需要使用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。