2014-10-02 17 views
11

Chính phủ của chúng tôi thích thay đổi giờ địa phương hoặc bật | tắt thời gian tiết kiệm ánh sáng ban ngày.
.NET có lịch sử thay đổi múi giờ không?

Bản vá được triển khai MS dành cho Nga để thay đổi thời gian mới.

Bây giờ có câu hỏi liệu lịch sử của các thay đổi có tồn tại không?

Khi tôi nhận được thời gian UTC trong ngày trong hệ thống 01.01.2000 nên nhớ rằng múi giờ Moscow có +3 UTC. (vào mùa hè +4) vào lúc đó.

Cho 01.01.2012 chúng tôi có +4 UTC cho cả mùa đông và mùa hè. Và chúng tôi sẽ sớm có +3 UTC.

thử nghiệm đơn giản cho thấy rằng .NET không lưu giữ hồ sơ về những thay đổi:

var t = new DateTime(2012,1,1); 
// UTC +4 expected 
System.Console.WriteLine(t.ToLocalTime()); 
// UTC +4 expected 
t = new DateTime(2012,06,1); 
System.Console.WriteLine(t.ToLocalTime()); 
// UTC +3 expected 
t = new DateTime(2000,1,1); 
System.Console.WriteLine(t.ToLocalTime()); 
// UTC +4 expected 
t = new DateTime(2000,6,1); 
System.Console.WriteLine(t.ToLocalTime()); 

Có một số API thêm tồn tại để đối phó với vấn đề này?

Cập nhật:

đã tìm thấy lớp TimeZoneInfo và liên quan AdjustmentRule lớp. Còn lại để kiểm tra xem tùy chỉnh múi giờ TimeZoneInfo.Local có ảnh hưởng đến API thời gian chờ hay không.

Cập nhật 2: Dường như bù trừ UTC không được lưu trữ làm lịch sử và AdjustmentRule chỉ thay đổi thời gian ban ngày trong năm.

+0

Hãy xem 'DateTimeOffset'. *** Nếu *** bạn có thể nắm bắt bù đắp múi giờ khi bạn nắm bắt dữ liệu bạn sẽ có hình dạng tốt hơn để hiển thị nó và tính toán chống lại nó. –

Trả lời

4

NET theo dõi một số lịch sử nhưng không phải lúc nào cũng chính xác. Bạn đã vấp phải một trong những điều không chính xác.

.NET nhập tất cả thông tin múi giờ của nó từ Windows qua sổ đăng ký, như được mô tả herehere. Nếu bạn nhìn vào sổ đăng ký tại HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\Russian Standard Time\Dynamic DST bạn sẽ thấy rằng nó chỉ theo dõi thông tin từ năm 2010 trở đi cho múi giờ này. Các ngày thử nghiệm trong năm 2000 sẽ không hoạt động tốt vì nó sẽ quay trở lại quy tắc sớm nhất có sẵn (2010).

cơ sở UTC bù đắp thông tin theo dõi trong registry, nhưng không trong lớp AdjustmentRule rằng NET nhập khẩu nó vào. Nếu bạn kiểm tra các quy tắc điều chỉnh cho múi giờ này, bạn sẽ thấy rằng năm 2012 và 2013 không được nhập vào tất cả:

var tz = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"); 
foreach (var rule in tz.GetAdjustmentRules()) 
{ 
    Console.WriteLine("{0:d} - {1:d}", rule.DateStart, rule.DateEnd); 
} 

OUTPUT:

1/1/0001 - 12/31/2010 
1/1/2011 - 12/31/2011 
1/1/2014 - 12/31/2014 

Mặc dù họ tồn tại trong Windows registry, 2012 và 2013 không được nhập vì không có điều chỉnh thời gian tiết kiệm ánh sáng ban ngày.

Điều này tạo ra sự cố khi thay đổi bù đắp cơ sở - như nó có cho múi giờ này. Vì hiện tại là +3, và hai năm mà nó là +4 không được nhập, thì sẽ có vẻ như là +3 cho những năm còn thiếu.

Không có giải pháp tốt cho việc này bằng cách sử dụng TimeZoneInfo. Ngay cả khi bạn cố gắng tạo múi giờ tùy chỉnh của riêng mình, bạn sẽ gặp sự cố khi kết hợp loại thay đổi này vào cấu trúc dữ liệu có sẵn.

May mắn thay, có một tùy chọn khác. Bạn có thể sử dụng tiêu chuẩn IANA time zones, qua thư viện Noda Time.

Các mã sau sử dụng Noda Thời gian để phù hợp với những gì bạn đã viết trong mã ban đầu của bạn:

DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault(); 
Console.WriteLine(Instant.FromUtc(2012, 1, 1, 0, 0).InZone(tz).LocalDateTime); 
Console.WriteLine(Instant.FromUtc(2012, 6, 1, 0, 0).InZone(tz).LocalDateTime); 
Console.WriteLine(Instant.FromUtc(2000, 1, 1, 0, 0).InZone(tz).LocalDateTime); 
Console.WriteLine(Instant.FromUtc(2000, 6, 1, 0, 0).InZone(tz).LocalDateTime); 

Nếu múi giờ địa phương của bạn chưa được thiết lập cho Moscow, bạn có thể thay đổi dòng đầu tiên:

DateTimeZone tz = DateTimeZoneProviders.Tzdb["Europe/Moscow"]; 

OUTPUT:

1/1/2012 4:00:00 AM 
6/1/2012 4:00:00 AM 
1/1/2000 3:00:00 AM 
6/1/2000 4:00:00 AM 

cập nhật

Sự cố được mô tả ở trên AdjustmentRule không theo dõi thay đổi bù đắp cơ sở được mô tả trong bài viết Hỗ trợ của Microsoft KB3012229 và sau đó được khắc phục trong Khuôn khổ .NET 4.6 và trong .NET Core.

Trong the reference sources, người ta có thể thấy rằng AdjustmentRule hiện giữ trường m_baseUtcOffsetDelta. Trong khi trường này không được hiển thị thông qua thuộc tính công khai, nó sẽ ảnh hưởng đến tính toán, và nó phản ánh trong tuần tự hóa nếu bạn sử dụng các phương thức FromSerializedStringToSerializedString (nếu có ai đó thực sự sử dụng).

+0

Đã có thay đổi vài ngày trước. Bây giờ 2012 và 2013 được nhập. Ít nhất trong .NET 4.5.2 (Win8.1, Win10) 1/1/0001 - 12/31/2010 1/1/2011 - 31/12/2011 1/1/2012 - 12/31/2012 1/1/2013 - 31/12/2013 1/1/2014 - 12/31/2014 Nhưng dữ liệu cho năm 2015 và 2016 ở đâu? –

+0

Thay đổi cuối cùng của Nga trong năm 2014 đã giảm thời gian tiết kiệm ánh sáng ban ngày, do đó không có quy tắc điều chỉnh cho năm 2015 và sau đó vì không có điều chỉnh; bù đắp được cố định. Giá trị cuối cùng của quy tắc cuối cùng trong danh sách phải luôn áp dụng từ thời điểm đó trở đi. –

+0

Ngoài ra, mặc dù bạn đang nhắm mục tiêu 4.5.2, tôi đoán bạn đã cài đặt 4.6 trên hộp để nó sử dụng bản sửa lỗi cho [KB3012229] (https://support.microsoft.com/en-us/kb/3012229) đã được triển khai trong 4.6 (KB vẫn cần được cập nhật để phản ánh điều đó). Tác dụng phụ là bây giờ bạn thấy các quy tắc chuyển đổi cho năm 2012 và 2013 bởi vì bây giờ nó đang theo dõi chính xác các thay đổi bù đắp cơ sở. –

2

dữ liệu múi giờ lịch sử là rất phức tạp và điền với nhiều ví dụ về các trường hợp ngoại lệ nhỏ mà áp dụng ở các khu vực địa lý cụ thể mà ngày nay không có cách nào dễ dàng được mô tả. Không chỉ là sự thay đổi vị trí, mà còn là những vùng mà chúng được áp dụng.

Có một dự án để mô hình lịch sử của dữ liệu này từ khắp nơi trên thế giới ở đây:

.NET không hỗ trợ những gì bạn muốn ra khỏi cái hộp.Việc đưa ra một giải pháp chung cho vấn đề sẽ rất khó khăn, tuy nhiên nếu bạn chỉ cần nó trên một vùng nhỏ, thì bạn có thể tự điền vào bằng cách sử dụng TimeZoneInfo class, tài liệu có trạng thái:

các thành viên của lớp hỗ trợ TimeZoneInfo các hoạt động sau đây:

  • Tạo một múi giờ mới mà chưa được xác định bởi các hệ điều hành
Các vấn đề liên quan