首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >我们如何开发针对闰年bug的编码实践呢?

我们如何开发针对闰年bug的编码实践呢?
EN

Stack Overflow用户
提问于 2012-03-10 22:38:11
回答 3查看 3.3K关注 0票数 80

微软刚刚宣布,上周在计算日期(跨越闰年) caused a major outage in Windows Azure时出现了软件错误。

在闰年绕过DateTime.Now.AddYears(1)的判断真的只是一个简单的错误吗?

什么样的编码实践可以避免这种情况?

编辑正如dcstraw指出的,在闰年的DateTime.Now.AddYears(1)实际上在.NET中返回了正确的日期,所以这不是一个框架错误,而是一个明显的日期计算错误。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-10 22:43:56

无耻的插头:

使用更好的日期和时间API

内置的.NET日期和时间库很难正确使用。它们确实允许你做你需要的一切,但是你不能通过类型系统清楚地表达你自己。DateTime is a messDateTimeOffset可能会让你认为你实际上保存了时区信息,而TimeZoneInfo不会强迫你去考虑所有你应该考虑的事情。

所有这些都不能很好地表示“一天中的某个时间”或“只是一个日期”,也没有明确区分“本地时间”和“特定时区的时间”。如果您希望使用公历之外的日历,则需要始终使用Calendar类。

所有这些都是我构建Noda Time的原因--在Joda Time“引擎”的一个端口上构建一个替代的日期和时间库,但上面有一个新的(更精简的) API。

一些你可能想要思考的要点,如果你没有意识到它们,很容易遗漏它们:

  • 将本地日期/时间映射到特定时区的日期/时间并不像您想象的那么简单。一个特定的本地日期/时间可能会出现一次、两次(模棱两可)或零次(跳过),因为夏令时transitions
  • Time区域在历史上有所不同--坦率地说,这超出了TimeZoneInfo通常愿意透露的范围。(它不支持“标准时间”概念随时间变化的时区,也不支持进入永久夏令时的时区。)
  • 即使使用zoneinfo数据库,时区ID也不一定是稳定的。(CLDR解决了这个问题;我希望在Noda time eventually.)
  • Textual中支持日期和时间的表示是一场噩梦,不仅仅是在排序方面,而且还有日期分隔符、时间分隔符和一些奇怪的东西,比如所有的月份名称
  • 。一天的开始并不总是午夜-例如,在巴西,春季夏令时转换将墙上的时钟从晚上11:59:59移动到凌晨1点
  • 在某些情况下(好吧,据我所知)一个时区可以强制跳过一整天-2011年12月30日不会发生在萨摩亚!我怀疑大多数开发人员可能会忽略这一点,但是...
  • 如果您要使用公历以外的日历,请小心并确保您真的知道您期望它如何表现。

就具体的开发实践而言:

我预计Noda Time的核心好处是迫使开发人员在各种不同的类型之间进行选择来表示他们的数据。做好这件事,其他的都是simpler.

  • Unit测试你能想到的一切。当然,这将取决于您的系统到底做了什么,但要特别考虑不同的时区、夏令时转换过程中发生的情况,当然还有闰年。

  • 我建议您注入一个“类似时钟的接口”--一种告诉当前时间的服务--而不是显式地调用DateTime.NowDateTime.UtcNow;这会让它变得更容易(可行!)如果你正在使用"now“执行多个操作,要对

  • 进行单元测试,只需获取日期/时间一次并记住它,而不是重复请求"now”--否则,值可能会在两次调用之间以不幸的方式更改。

  • “Do everything in UTC”也不总是答案--如果我想知道“两周后”在本地时区的确切时间是什么时候?“然后我需要存储本地日期/时间以及时区。
票数 95
EN

Stack Overflow用户

发布于 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

我并不是说DateTimeDateTimeOffset不容易出错,只是我不认为它们会导致这个特定的问题。

票数 25
EN

Stack Overflow用户

发布于 2012-03-14 07:35:06

我们如何开发代码实践,以防止闰年错误?什么样的编码实践可以避免这种情况?

正如John提到的那样,单元测试特定日期是一种代码实践,它将会有所帮助,但是没有什么比我定义的“手动集成测试”更好的了。

更改开发/测试床服务器上的时钟,并观察时间一过就会发生什么。

不要纠结于这是否是一种“编码实践”--显然你不可能在日历上的每一天都这样做--选择你关心的日期,无论是2月29日、月底还是夏令时转换日期。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9647269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档