14

在 DateTime 上使用 AddYears 方法时,任何人都可以解释.NET 中闰年计算背后的数学原理或简单原因吗?

  • 如果您选择 2012 年 2 月 29 日并添加一年,您将得到 2013 年 2 月 28 日,而不是 2013 年 3 月 1 日(一年后的前一天)。
  • 如果您在 2012 年 1 月 31 日加上一年,您将得到 2013 年 1 月 31 日(一年后的同一日期)。

我想大多数人会假设“从 29.02.leapX 开始的一年是 01.03.leapX+1”。

例子:

// Testing with 29th Feb
var now1 = DateTime.Parse("2012-02-29 15:00:00");

var results1 = new DateTime[]
{
    now1.AddYears(1),
    now1.AddYears(2),
    now1.AddYears(3),
    now1.AddYears(4)
};

foreach(var dt in results1)
{
    Console.WriteLine(dt.ToString("s"));
}

// Output:
// 2013-02-28T15:00:00
// 2014-02-28T15:00:00
// 2015-02-28T15:00:00
// 2016-02-29T15:00:00


// Testing with 31st Jan
var now2 = DateTime.Parse("2012-01-31 13:00:00");

var results2 = new DateTime[]
{
    now2.AddYears(1),
    now2.AddYears(2),
    now2.AddYears(3),
    now2.AddYears(4)
};

foreach(var dt in results2)
{
    Console.WriteLine(dt.ToString("s"));
}

// Output:
// 2013-01-31T13:00:00
// 2014-01-31T13:00:00
// 2015-01-31T13:00:00
// 2016-01-31T13:00:00
4

3 回答 3

19

我想大多数人会假设“从 29.02.leapX 开始的一年是 01.03.leapX+1”。

我不会。我通常会期望截断。这与在 1 月 30 日增加一个月基本相似——我希望得到 2 月的最后一天。在这两种情况下,您都添加了“较大的单位”(月或年),而“较小的单位”(天)将被截断以适应年/月组合。

(这也是Joda TimeNoda Time的行为方式,顺便说一句。)

正如蒂姆在评论中提到的那样,它也是这样记录的:

AddYears 方法计算结果年份时考虑闰年。生成的 DateTime 对象的月份和时间部分与此实例保持相同。

所以月份必须保持为二月;显然,年份将根据添加的年数而变化-因此必须调整日期以保持有效。

于 2012-02-29T11:32:14.463 回答
2

根据您的理由,当您添加一年时,2012 年 3 月 1 日将变为 2012 年 3 月 2 日。如果你在之前的所有闰年都加上这个转变,那么你会发现你的计算非常不稳定。唯一明智的反应是返回非闰年的 2 月 28 日。

于 2012-02-29T11:32:48.720 回答
-1

这很有趣,虚无..

例如,有时会使用此功能:

private static int Age(DateTime birthDate, DateTime asAtDate)
{
    // Calculate age in years
    int age = asAtDate.Year - birthDate.Year;
    if (asAtDate < birthDate.AddYears(age)) age--;
    if (age < 0) age = 0;
    return age;
}

如果一个人出生于 2016 年 2 月 29 日,此函数将得出结论,他们在 2017 年 2 月 28 日已满 1 岁。

我按照以下方式记录了 Excel 函数示例:

=DATEDIF(DATE(2016,2,28),DATE(2017,2,28),"Y")     
   gives result of 1
=DATEDIF(DATE(2016,2,29),DATE(2017,2,28),"Y")
   gives result of 0
=DATEDIF(DATE(2016,2,29),DATE(2017,3,1),"Y")
   gives result of 1
=DATEDIF(DATE(2016,3,1),DATE(2017,3,1),"Y")
   gives result of 1
于 2019-09-19T23:43:40.780 回答