leap年错误的一些例子是什么?

Mat*_*int 7 datetime anti-patterns date leap-year

year年错误是一种代码缺陷,当在a 的环境中(通常是在公历阳历系统中)执行时,会产生有问题的意外结果。

上一个leap年是2016年。下一个leap年是2020年和2024年。

leap年有两个独特的属性:

  • years年有2月29日,而普通年没有。
  • 年总共有366天,而普通年只有365天。

这篇文章旨在帮助其他人了解of年错误的性质,它们在各种语言中的外观以及如何纠正它们。

年错误通常分为两种影响类别:

  • 类别1:导致错误条件的变量,例如异常,错误返回代码,未初始化的变量或无限循环
  • 类别2:导致错误数据的那些,例如范围查询或聚合中的一对一问题

对于每个答案,请指出编程语言和/或平台,以及上面定义的影响类别。(请遵循现有答案使用的模板。)

请针对每种语言和缺陷类型创建一个单独的答案,并投票给您最喜欢的,尤其是您亲身遇到的那些投票(在可能的情况下留下带有轶事的评论)。

我将提供一些答案以开始使用,并随着时间的推移以其他示例进行更新。

Mat*_*int 8

.NET / C# - 从日期部分构建

影响类别 1

有缺陷的代码

DateTime dt = DateTime.Now;
DateTime result = new DateTime(dt.Year + 1, dt.Month, dt.Day);
Run Code Online (Sandbox Code Playgroud)

此代码将正常工作,直到dt成为 2 月 29 日。然后,它将尝试创建一个不存在的普通年份的 2 月 29 日。该DateTime构造函数将抛出ArgumentOutOfRangeException

变体包括接受年、月和日参数的任何形式DateTimeDateTimeOffset构造函数,当这些值来自不同来源或在不考虑整体有效性的情况下进行操作时。

更正代码

DateTime dt = DateTime.Now;
DateTime result = dt.AddYears(1);
Run Code Online (Sandbox Code Playgroud)

常见变化 - 生日(和其他纪念日)

一种变化是在确定用户当前生日时不考虑跨越(2 月 29 日出生的人)。它也适用于其他类型的周年纪念日,例如雇用日期、服务日期、计费日期等。

有缺陷的代码

DateTime birthdayThisYear = new DateTime(DateTime.Now.Year, dob.Month, dob.Day);
Run Code Online (Sandbox Code Playgroud)

这种方法需要调整,例如以下使用 2 月 28 日作为普通年份。(不过,根据用例,3 月 1 日可能是首选。)

更正代码

int year = DateTime.Now.Year;
int month = dob.Month;
int day = dob.Day;
if (month == 2 && day == 29 && !DateTime.IsLeapYear(year))
    day--;

DateTime birthdayThisYear = new DateTime(year, month, day);
Run Code Online (Sandbox Code Playgroud)

更正的代码(替代实现)

DateTime birthdayThisYear = dob.AddYears(DateTime.Now.Year - dob.Year);
Run Code Online (Sandbox Code Playgroud)