微软刚刚宣布,上周在计算日期(跨越闰年) caused a major outage in Windows Azure时出现了软件错误。
在闰年绕过DateTime.Now.AddYears(1)
的判断真的只是一个简单的错误吗?
什么样的编码实践可以避免这种情况?
编辑正如dcstraw指出的,在闰年的DateTime.Now.AddYears(1)
实际上在.NET中返回了正确的日期,所以这不是一个框架错误,而是一个明显的日期计算错误。
发布于 2012-03-10 22:43:56
无耻的插头:
使用更好的日期和时间API
内置的.NET日期和时间库很难正确使用。它们确实允许你做你需要的一切,但是你不能通过类型系统清楚地表达你自己。DateTime
is a mess,DateTimeOffset
可能会让你认为你实际上保存了时区信息,而TimeZoneInfo
不会强迫你去考虑所有你应该考虑的事情。
所有这些都不能很好地表示“一天中的某个时间”或“只是一个日期”,也没有明确区分“本地时间”和“特定时区的时间”。如果您希望使用公历之外的日历,则需要始终使用Calendar
类。
所有这些都是我构建Noda Time的原因--在Joda Time“引擎”的一个端口上构建一个替代的日期和时间库,但上面有一个新的(更精简的) API。
一些你可能想要思考的要点,如果你没有意识到它们,很容易遗漏它们:
TimeZoneInfo
通常愿意透露的范围。(它不支持“标准时间”概念随时间变化的时区,也不支持进入永久夏令时的时区。)就具体的开发实践而言:
我预计Noda Time的核心好处是迫使开发人员在各种不同的类型之间进行选择来表示他们的数据。做好这件事,其他的都是simpler.
DateTime.Now
或DateTime.UtcNow
;这会让它变得更容易(可行!)如果你正在使用"now“执行多个操作,要对
发布于 2012-03-11 00:13:33
值得注意的是,bug可能不是由于您发布的一行代码造成的:
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
是闰日,就会抛出一个异常。然而,微软关于Azure问题的博客说,他们在2013年2月29日创建了一个无效的日期,我不确定这是否可以在.NET中使用DateTime
。
我并不是说DateTime
和DateTimeOffset
不容易出错,只是我不认为它们会导致这个特定的问题。
发布于 2012-03-14 07:35:06
我们如何开发代码实践,以防止闰年错误?什么样的编码实践可以避免这种情况?
正如John提到的那样,单元测试特定日期是一种代码实践,它将会有所帮助,但是没有什么比我定义的“手动集成测试”更好的了。
更改开发/测试床服务器上的时钟,并观察时间一过就会发生什么。
不要纠结于这是否是一种“编码实践”--显然你不可能在日历上的每一天都这样做--选择你关心的日期,无论是2月29日、月底还是夏令时转换日期。
https://stackoverflow.com/questions/9647269
复制相似问题