Nhận múi giờ từ DateTime


103

.Net DateTime có chứa thông tin về múi giờ nơi nó được tạo không?

Tôi có một thư viện phân tích cú pháp DateTime từ định dạng có "+ zz" ở cuối và trong khi nó phân tích cú pháp chính xác và điều chỉnh giờ địa phương, tôi cần lấy múi giờ cụ thể từ đối tượng DateTime.

cái này nó có hoàn toàn có thể xảy ra được không? Tất cả những gì tôi có thể thấy là DateTime.Kind, chỉ định xem thời gian là cục bộ hay UTC.


Xem ghi chú trên tài liệu DateTime.Parse để xử lý múi giờ và DateTimeStyles. Nhưng không, điều bạn muốn thực sự không thể thực hiện được.
yoyo

Câu trả lời:


136

Bản thân DateTime không chứa thông tin múi giờ thực. Nó có thể biết đó là UTC hay local, nhưng không phải local nghĩa là gì.

DateTimeOffset có phần tốt hơn - về cơ bản đó là thời gian UTC và phần bù. Tuy nhiên, điều đó vẫn chưa thực sự đủ để xác định múi giờ, vì nhiều múi giờ khác nhau có thể có cùng độ lệch tại bất kỳ thời điểm nào. Điều này nghe có vẻ như nó có thể đủ tốt cho bạn, vì tất cả những gì bạn phải làm khi phân tích cú pháp ngày / giờ là phần bù.

Sự hỗ trợ cho các múi giờ kể từ .NET 3.5 tốt hơn rất nhiều so với trước đây, nhưng tôi thực sự muốn xem "ZonedDateTime" tiêu chuẩn hoặc tương tự như vậy - giờ UTC và múi giờ thực tế. Thật dễ dàng để xây dựng của riêng bạn, nhưng sẽ rất tuyệt nếu thấy nó trong các thư viện tiêu chuẩn.

CHỈNH SỬA: Gần bốn năm sau, bây giờ tôi khuyên bạn nên sử dụng Noda Time có bộ ngày / giờ phong phú hơn. Tuy nhiên, tôi thiên vị, với tư cách là tác giả chính của Noda Time :)


2
Dự án PublicDomain trên CodePlex thực hiện điều này cho bạn.
Cheeso

Một enum TimeZone trong BCL sẽ rất tốt nếu múi giờ thế giới là tĩnh và không thay đổi.
Jeff LaFay

1
@jlafay: Tuy nhiên, chúng có thay đổi - chẳng hạn như nhiều múi giờ hơn đã được thêm vào Windows chỉ năm ngoái.
Jon Skeet

Dự án này không còn được duy trì bởi tác giả; publicdomain.codeplex.com Có vẻ như điều này có thể hữu ích, tùy thuộc vào cách sử dụng, người ta phải đặt nó trước khi sử dụng; timezone.codeplex.com
AnneTheAgile

3
@AnneTheAgile: Cá nhân tôi khuyên bạn nên sử dụng thư viện Noda Time của riêng mình, tất nhiên :)
Jon Skeet

36

Không.

Nhà phát triển chịu trách nhiệm theo dõi thông tin múi giờ được liên kết với giá trị DateTime thông qua một số cơ chế bên ngoài.

Một trích dẫn từ một bài báo xuất sắc ở đây . A phải đọc cho mọi nhà phát triển .Net.

Vì vậy, lời khuyên của tôi là hãy viết một lớp wrapper nhỏ phù hợp với nhu cầu của bạn.



2

Bạn có thể sử dụng lớp TimeZoneInfo

Lớp TimeZone nhận dạng múi giờ địa phương và có thể chuyển đổi thời gian giữa Giờ phối hợp quốc tế (UTC) và giờ địa phương. Một đối tượng TimeZoneInfo có thể đại diện cho bất kỳ múi giờ nào và các phương thức của lớp TimeZoneInfo có thể được sử dụng để chuyển đổi thời gian trong một múi giờ thành thời gian tương ứng trong bất kỳ múi giờ nào khác. Các thành viên của lớp TimeZoneInfo hỗ trợ các hoạt động sau:

  1. Truy xuất múi giờ đã được xác định bởi hệ điều hành.

  2. Liệt kê các múi giờ có sẵn trên hệ thống.

  3. Thời gian chuyển đổi giữa các múi giờ khác nhau.

  4. Tạo múi giờ mới chưa được hệ điều hành xác định.

    Sắp xếp thứ tự một múi giờ để truy xuất sau này.


1
... nhưng, với DateTime, vẫn không có cách nào để sử dụng TimeZoneInfo để xác định TimeZone của DateTime, theo hiểu biết của tôi.
Remi Despres-Smyth

@ RemiDespres-Smyth Tôi chỉ lưu trữ TimeZoneInfo cùng với DateTime trong 1 lớp.
Konrad


0

Nói chung, thực hành sẽ là chuyển dữ liệu dưới dạng DateTime với "múi giờ" là UTC và sau đó chuyển đối tượng TimeZoneInfo và khi bạn đã sẵn sàng hiển thị dữ liệu, bạn sử dụng đối tượng TimeZoneInfo để chuyển đổi UTC DateTime.

Tùy chọn khác là đặt DateTime với múi giờ hiện tại và sau đó đảm bảo rằng "múi giờ" là không xác định cho đối tượng DateTime, sau đó đảm bảo DateTime được chuyển lại với TimeZoneInfo cho biết TimeZone của DateTime đã được truyền.

Như những người khác đã chỉ ra ở đây, sẽ rất tuyệt nếu Microsoft vượt lên trên điều này và tạo ra một đối tượng tốt để làm tất cả, nhưng bây giờ bạn phải xử lý hai đối tượng.


0

DateTime không biết độ lệch múi giờ của nó. Không có phương thức tích hợp nào để trả về giá trị chênh lệch hoặc tên múi giờ (ví dụ: EAT, CEST, EST, v.v.).

Giống như những người khác đề xuất, bạn có thể chuyển đổi ngày của mình thành UTC:

DateTime localtime = new DateTime.Now;
var utctime = localtime.ToUniversalTime();

và sau đó chỉ tính toán sự khác biệt:

TimeSpan difference = localtime - utctime;

Ngoài ra, bạn có thể chuyển đổi lần này sang lần khác bằng cách sử dụng DateTimeOffset:

DateTimeOffset targetTime = DateTimeOffset.Now.ToOffset(new TimeSpan(5, 30, 0));

Nhưng đây là kiểu nén có tổn thất - riêng phần bù không thể cho bạn biết đó là múi giờ nào vì hai quốc gia khác nhau có thể ở các múi giờ khác nhau và có cùng thời gian chỉ trong một phần của năm (ví dụ: Nam Phi và Châu Âu). Ngoài ra, hãy lưu ý rằng thời gian tiết kiệm ánh sáng ban ngày vào mùa hè có thể được áp dụng vào các ngày khác nhau (EST và CET - chênh lệch 3 tuần).

Bạn có thể lấy tên của múi giờ hệ thống cục bộ của mình bằng cách sử dụng lớp TimeZoneInfo:

TimeZoneInfo localZone = TimeZoneInfo.Local;
localZone.IsDaylightSavingTime(localtime) ? localZone.DaylightName : localZone.StandardName

Tôi đồng ý với Gerrie Schenck, hãy đọc bài viết mà anh ấy gợi ý.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.