DateTimeOffset
là một đại diện của thời gian tức thời (còn được gọi là thời gian tuyệt đối ). Theo đó, tôi có nghĩa là một khoảnh khắc thời gian là phổ quát cho tất cả mọi người (không tính đến giây nhuận , hoặc các hiệu ứng tương đối của sự giãn nở thời gian ). Một cách khác để mô tả thời gian tức là với một DateTime
nơi .Kind
là DateTimeKind.Utc
.
Điều này khác với thời gian theo lịch (còn được gọi là giờ dân sự ), là một vị trí trên lịch của ai đó và có nhiều lịch khác nhau trên toàn cầu. Chúng tôi gọi những múi giờ này . Hiện Lịch được đại diện bởi một DateTime
nơi .Kind
là DateTimeKind.Unspecified
hay DateTimeKind.Local
. Và .Local
chỉ có ý nghĩa trong các tình huống mà bạn có một sự hiểu biết ngụ ý về nơi máy tính đang sử dụng kết quả được định vị. (Ví dụ: máy trạm của người dùng)
Vậy thì, tại sao DateTimeOffset
thay vì UTC DateTime
? Đó là tất cả về quan điểm. Chúng ta hãy sử dụng một sự tương tự - chúng ta sẽ giả làm nhiếp ảnh gia.
Hãy tưởng tượng bạn đang đứng trên dòng thời gian lịch, hướng máy ảnh vào một người trên dòng thời gian tức thời được đặt trước mặt bạn. Bạn sắp xếp máy ảnh của mình theo các quy tắc múi giờ của bạn - thay đổi định kỳ do thời gian tiết kiệm ánh sáng ban ngày hoặc do những thay đổi khác đối với định nghĩa pháp lý về múi giờ của bạn. (Bạn không có bàn tay chắc chắn, vì vậy máy ảnh của bạn bị rung.)
Người đứng trong bức ảnh sẽ nhìn thấy góc mà máy ảnh của bạn đến từ đâu. Nếu những người khác đang chụp ảnh, họ có thể từ các góc độ khác nhau. Đây là những gì Offset
một phần của DateTimeOffset
đại diện.
Vì vậy, nếu bạn gắn nhãn máy ảnh của mình là "Giờ phương Đông", đôi khi bạn chỉ từ -5 và đôi khi bạn chỉ từ -4. Có máy ảnh trên khắp thế giới, tất cả đều được dán nhãn những thứ khác nhau, và tất cả đều chỉ vào cùng một dòng thời gian tức thời từ các góc độ khác nhau. Một số trong số chúng nằm ngay cạnh (hoặc trên đỉnh) của nhau, vì vậy chỉ cần biết phần bù không đủ để xác định múi giờ mà thời gian có liên quan.
Còn UTC thì sao? Chà, đó là một chiếc máy ảnh ngoài kia được đảm bảo có một bàn tay chắc chắn. Nó nằm trên giá ba chân, neo chắc chắn xuống đất. Nó không đi đâu cả. Chúng tôi gọi góc nhìn của nó là độ lệch bằng không.
Vậy - sự tương tự này nói với chúng ta điều gì? Nó cung cấp một số hướng dẫn trực quan-
Nếu bạn đại diện cho thời gian liên quan đến một nơi cụ thể, hãy biểu thị thời gian theo lịch với a DateTime
. Chỉ cần chắc chắn rằng bạn không bao giờ nhầm lẫn một lịch với nhau. Unspecified
nên là giả định của bạn. Local
chỉ hữu ích đến từ DateTime.Now
. Ví dụ, tôi có thể lấy DateTime.Now
và lưu nó trong cơ sở dữ liệu - nhưng khi tôi truy xuất nó, tôi phải thừa nhận rằng nó là như vậy Unspecified
. Tôi không thể tin rằng lịch địa phương của tôi giống với lịch ban đầu được lấy từ đó.
Nếu bạn phải luôn chắc chắn về thời điểm này, hãy chắc chắn rằng bạn đang đại diện cho thời gian tức thời. Sử dụng DateTimeOffset
để thực thi nó, hoặc sử dụng UTC DateTime
theo quy ước.
Nếu bạn cần theo dõi một khoảnh khắc của thời gian tức thời, nhưng bạn cũng muốn biết "Thời gian nào người dùng nghĩ rằng đó là trên lịch địa phương của họ?" - thì bạn phải sử dụng a DateTimeOffset
. Điều này rất quan trọng đối với các hệ thống chấm công, ví dụ - cả về mối quan tâm kỹ thuật và pháp lý.
Nếu bạn cần sửa đổi một bản ghi đã được ghi lại trước đó DateTimeOffset
- bạn không có đủ thông tin trong phần bù để đảm bảo rằng phần bù mới vẫn phù hợp với người dùng. Bạn cũng phải lưu trữ một mã định danh múi giờ (nghĩ - tôi cần tên của máy ảnh đó để tôi có thể chụp ảnh mới ngay cả khi vị trí đã thay đổi).
Cũng cần chỉ ra rằng Noda Time có một đại diện được gọi ZonedDateTime
cho điều này, trong khi thư viện lớp cơ sở .Net không có gì tương tự. Bạn sẽ cần lưu trữ cả a DateTimeOffset
và một TimeZoneInfo.Id
giá trị.
Đôi khi, bạn sẽ muốn đại diện cho một thời gian theo lịch là "địa phương đang xem nó". Ví dụ, khi xác định những gì ngày nay có nghĩa. Hôm nay luôn luôn là nửa đêm đến nửa đêm, nhưng chúng đại diện cho một số lượng phạm vi chồng chéo gần như vô tận trên dòng thời gian tức thời. (Trong thực tế, chúng tôi có số lượng múi giờ hữu hạn, nhưng bạn có thể thể hiện độ lệch xuống mức tích tắc) Vì vậy, trong những tình huống này, hãy đảm bảo bạn hiểu cách hạn chế "ai hỏi?" đặt câu hỏi xuống một múi giờ duy nhất, hoặc giải quyết việc dịch chúng trở lại thời gian tức thời khi thích hợp.
Dưới đây là một vài thông tin nhỏ khác về DateTimeOffset
sự tương tự này và một số mẹo để giữ cho nó thẳng:
Nếu bạn so sánh hai DateTimeOffset
giá trị, đầu tiên chúng được chuẩn hóa thành zero offset trước khi so sánh. Nói cách khác, 2012-01-01T00:00:00+00:00
và 2012-01-01T02:00:00+02:00
đề cập đến cùng một khoảnh khắc tức thời, và do đó là tương đương.
Nếu bạn đang làm bất kỳ kiểm tra đơn vị và cần phải chắc chắn trong những bù đắp, kiểm tra cả các DateTimeOffset
giá trị, và các .Offset
tài sản riêng.
Có một chuyển đổi ngầm định một chiều được tích hợp trong khung .Net cho phép bạn chuyển một tham số hoặc DateTime
bất kỳ DateTimeOffset
tham số nào . Khi làm như vậy, các .Kind
vấn đề . Nếu bạn vượt qua một loại UTC, nó sẽ mang theo với độ lệch bằng 0, nhưng nếu bạn vượt qua .Local
hoặc .Unspecified
, nó sẽ giả sử là cục bộ . Khung cơ bản là nói, "Chà, bạn đã yêu cầu tôi chuyển đổi thời gian lịch sang thời gian tức thời, nhưng tôi không biết điều này đến từ đâu, vì vậy tôi sẽ sử dụng lịch địa phương." Đây là một vấn đề lớn nếu bạn tải lên một thông tin không xác định DateTime
trên máy tính có múi giờ khác. (IMHO - điều đó sẽ tạo ra một ngoại lệ - nhưng không.)
Ổ cắm không biết xấu hổ:
Nhiều người đã chia sẻ với tôi rằng họ thấy sự tương tự này vô cùng quý giá, vì vậy tôi đã đưa nó vào khóa học Pluralsight của mình, Nguyên tắc cơ bản về Ngày và Giờ . Bạn sẽ tìm thấy hướng dẫn từng bước của sự tương tự máy ảnh trong mô-đun thứ hai, "Các vấn đề bối cảnh", trong clip có tiêu đề "Thời gian lịch so với thời gian tức thời".