2012-02-29 38 views
10

Bất cứ ai có thể giải thích toán học hay đơn giản là lý do đằng sau các phép tính năm nhuận trong .NET khi sử dụng phương thức AddYears trên DateTime?Hành vi của DateTime.AddYears vào năm nhuận

  • Nếu bạn thực hiện ngày 29 tháng 2 năm 2012 và thêm một năm, bạn nhận được ngày 28 tháng 2 năm 2013, không phải ngày 1 tháng 3 năm 2013 (ngày trước một năm sau).
  • Nếu bạn thêm một năm đến ngày 31 tháng 1 năm 2012, bạn nhận được ngày 31 tháng 1 năm 2013 (cùng một ngày sau một năm).

Tôi nghĩ hầu hết mọi người sẽ giả định rằng "một năm từ 29.02.leapX là 01.03.leapX + 1".

Ví dụ:

// 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 
+3

[MSDN] (http://msdn.microsoft.com/en-us/library/system.datetime.addyears.aspx) khá rõ ràng: "Phương pháp AddYears tính toán năm kết quả tính đến năm nhuận. phần tháng và thời gian trong ngày của đối tượng DateTime kết quả vẫn giữ nguyên như thể hiện này. " –

Trả lời

11

Tôi nghĩ rằng hầu hết mọi người sẽ cho rằng "một năm kể từ 29.02.leapX là 01.03.leapX + 1".

Tôi không thích. Tôi thường mong đợi cắt ngắn. Về cơ bản nó tương tự như thêm một tháng đến ngày 30 tháng 1 - tôi mong đợi để có được ngày cuối cùng vào tháng Hai. Trong cả hai trường hợp, bạn đang thêm "đơn vị lớn hơn" (tháng hoặc năm) và "đơn vị nhỏ hơn" (ngày) đang được cắt ngắn để phù hợp với kết hợp năm/tháng.

(. Đây là cách Joda TimeNoda Time cư xử quá, btw)

Như Tim nêu trong ý kiến, đó là documented rằng cách quá:

Phương pháp AddYears tính năm kết quả có tính đến bước nhảy vọt tài khoản năm. Phần tháng và thời gian trong ngày của đối tượng DateTime kết quả vẫn giữ nguyên như thể hiện này.

Vì vậy, tháng phải giữ nguyên là tháng 2; năm sẽ thay đổi dựa trên bao nhiêu năm đang được thêm vào, rõ ràng - vì vậy ngày phải điều chỉnh để duy trì hiệu lực.

+0

Cảm ơn. Điều này có ý nghĩa với tôi, tuy nhiên tôi nhận ra tôi đã nghĩ về ngày tháng và lịch là mảng chồng chéo nơi "chỉ số" của 29.02 sẽ giống như chỉ số của 01.03 năm không nhuận sau. Một suy nghĩ rất đơn giản (và sai). – Henrik

+0

Một năm luôn là 12 tháng, nhưng 12 tháng có thể là 365 hoặc 366 ngày và mỗi tháng riêng lẻ có thể là một số ngày khác nhau, từ 28 đến 31. Một ngày luôn là 24 giờ, vì vậy Thêm phương thức cho Ngày, Giờ , vv sẽ chính xác mà không có sự thay đổi vì độ dài của một ngày không thay đổi theo ngày cho mỗi tùy chỉnh. Như dự kiến, nếu bạn thêm 365 ngày đến 1/1/2000, bạn nhận được 12/31/2000, bởi vì có 366 ngày trong năm đó. AddYears và AddMonths khác nhau, bởi vì ý nghĩa hoặc độ dài của một năm thay đổi theo năm, giống như độ dài của một tháng thay đổi theo tháng. – Triynko

+0

Điều này có nghĩa là một ngày tháng như ngày 15 tháng 3, thêm "một tháng" vào giá trị đó là mơ hồ về mặt kỹ thuật, vì nó liên quan đến số ngày trong cả tháng 3 và tháng 4.Vì nó là mơ hồ, để tránh "trôi dạt" người ta phải giữ ngày không đổi và tăng tháng, tăng mỗi 12 tháng một lần. Làm như vậy có thể dẫn đến các số "vượt quá giới hạn", và vì vậy ngày phải được thay đổi. Thay đổi ngày chỉ nên xảy ra trong bước cuối cùng. Thật thú vị, gọi AddMonths (2) vào "Jan 31" cho một giá trị khác "Mar 31" so với gọi AddMonth (1) hai lần liên tiếp trên giá trị trung gian "Feb 28" -> "Mar 28";) – Triynko

2

Với lý do của bạn thì 1 tháng 3 năm 2012 sẽ trở thành ngày 2 tháng 3 năm 2012 khi bạn thêm một năm. Nếu bạn thêm thay đổi này cho tất cả các năm nhuận trước đó thì bạn sẽ tìm thấy tính toán của bạn ồ ạt trôi dạt. Phản ứng hợp lý duy nhất là trả lại 28 tháng 2 cho những năm không nhuận.