微软刚刚宣布,计算日期(超过leap年)的软件错误导致上周Windows Azure发生了严重故障。
在judgment年期间进行判断时,这真的是一个简单的错误DateTime.Now.AddYears(1)
吗?
哪些编码惯例可以阻止这种情况?
编辑
dcstraw指出,DateTime.Now.AddYears(1)
on年实际上确实会在.NET中返回正确的日期。因此,这不是框架错误,但显然是日期计算中的错误。
微软刚刚宣布,计算日期(超过leap年)的软件错误导致上周Windows Azure发生了严重故障。
在judgment年期间进行判断时,这真的是一个简单的错误DateTime.Now.AddYears(1)
吗?
哪些编码惯例可以阻止这种情况?
编辑
dcstraw指出,DateTime.Now.AddYears(1)
on年实际上确实会在.NET中返回正确的日期。因此,这不是框架错误,但显然是日期计算中的错误。
Answers:
无耻的插头:
使用更好的日期和时间API
内置的.NET日期和时间库很难正确使用。它们确实可以让您做所需的一切,但是您无法通过类型系统清楚地表达自己。真是DateTime
一团糟,DateTimeOffset
可能会让您误以为自己实际上是在保留时区信息,并且TimeZoneInfo
不会强迫您考虑所有应考虑的事项。
这些都不提供说“一天中的某个时间”或“只是一个日期”的好方法,也没有在“本地时间”和“特定时区的时间”之间做出明确区分。而且,如果您要使用公历以外的日历,则需要一直进行该Calendar
课程。
所有这些都是为什么我要构建Noda Time的原因-替代的日期和时间库建立在Joda Time “引擎”的端口上,但顶部具有新的(更精简的)API。
您可能要考虑的一些要点,如果您不了解它们,就很容易错过:
TimeZoneInfo
坦率地说,时区比一般人更愿意透露。(它不支持“标准时间”的概念随时间而变化的时区,或者不属于永久性的夏令时。)就具体的开发实践而言:
DateTime.Now
or DateTime.UtcNow
;它使单元测试更加容易(可行!)值得注意的是,该错误可能不是由于您发布的一行引起的:
DateTime.Now.AddYears(1)
那不会创建一个无效的日期。如果您运行:
(new DateTime(2012, 2, 29)).AddYears(1)
您会在2013年2月28日得到通知。我不知道Azure的来宾代理编写的内容,但一定是另一个失败的呼叫。在.NET中执行此操作的不良方法是:
new DateTime(today.Year + 1, today.Month, today.Day)
如果today
是leap日,那将引发例外。但是,有关Azure问题的Microsoft博客说,他们创建了一个无效的日期2013年2月29日,我不确定DateTime
在.NET中是否可以这样做。
我不是说DateTime
和DateTimeOffset
不容易出错,只是我不认为他们会造成这一具体问题。