Lưu trữ DateTime (UTC) so với lưu trữ DateTimeOffset


93

Tôi thường có một "bộ chặn" ngay trước khi đọc / ghi từ / vào cơ sở dữ liệu thực hiện chuyển đổi DateTime (từ UTC sang giờ địa phương và từ giờ địa phương sang UTC), vì vậy tôi có thể sử dụng DateTime.Now(dẫn xuất và so sánh) trên toàn hệ thống mà không cần lo lắng về múi giờ.

Về tuần tự hóa và di chuyển dữ liệu giữa các máy tính, không cần phải bận tâm, vì ngày giờ luôn là UTC.

Tôi có nên tiếp tục lưu trữ ngày tháng của mình (SQL 2008 - datetime) ở định dạng UTC hay thay vào đó tôi nên lưu trữ nó bằng cách sử dụng DateTimeOffset(SQL 2008 - datetimeoffset)?

UTC Ngày trong cơ sở dữ liệu (kiểu ngày giờ) đã hoạt động và được biết đến rất lâu, tại sao lại thay đổi nó? Các lợi thế là gì?

Tôi đã xem xét các bài báo như thế này , nhưng tôi không bị thuyết phục 100%. Có suy nghĩ gì không?



1
Xem thêm: DateTime vs DateTimeOffset - được viết cho .Net, nhưng về mặt khái niệm cũng áp dụng cho SQL.
Matt Johnson-Pint

Câu trả lời:


131

Có một sự khác biệt rất lớn, đó là bạn không thể sử dụng UTC một mình.

  • Nếu bạn có một tình huống như thế này

    • Một máy chủmột số máy khách (tất cả theo địa lý ở các múi giờ khác nhau )
    • Khách hàng tạo một số dữ liệu với thông tin ngày giờ
    • Khách hàng lưu trữ tất cả trên máy chủ trung tâm
  • Sau đó:

    • datetimeoffset lưu trữ Giờ địa phương của khách hàng và CŨNG được bù đắp theo giờ UTC
    • tất cả các khách hàng đều biết thời gian UTC của tất cả dữ liệu và cả giờ địa phương ở nơi thông tin bắt nguồn
  • Nhưng:

    • Ngày giờ UTC chỉ lưu trữ ngày giờ UTC , vì vậy bạn không có thông tin về giờ địa phương ở vị trí khách hàng nơi bắt nguồn dữ liệu
    • Các khách hàng khác không biết giờ địa phương của địa điểm, thông tin ngày giờ đến từ đâu
    • Các ứng dụng khách khác chỉ có thể tính giờ địa phương của họ từ cơ sở dữ liệu (sử dụng giờ UTC) chứ không phải giờ địa phương của ứng dụng khách, nơi bắt nguồn dữ liệu

Ví dụ đơn giản là hệ thống đặt vé máy bay ... Vé máy bay phải có 2 thời điểm: - thời gian "cất cánh" (theo múi giờ của thành phố "Từ") - thời gian "hạ cánh" (theo múi giờ của thành phố "Điểm đến")


2
Đây là lời giải thích tốt nhất mà tôi đã đọc về thời điểm thích hợp, và tôi đã đọc rất nhiều Đối với chúng tôi, từ điều này, có vẻ như không phải vậy. Chúng tôi có thời gian theo giờ UTC cho dữ liệu bên ngoài của mình và chúng tôi biết vị trí từ một nguồn khác nếu cần (và chưa bao giờ có). Cảm ơn vì đã làm cho nó có vẻ quá rõ ràng.
Andrew Backer

19
bạn đã nói "datetimeoffset lưu trữ thời gian UTC và CŨNG được bù đắp theo giờ địa phương của khách hàng", nhưng datetimeoffset lưu trữ thời gian ĐỊA PHƯƠNG + Chênh lệch hoặc thời gian UTC + bù đắp bằng +0.
Serhii Kyslyi

mặc dù bạn chỉ có thể cast DTO đến một DT kể từ khi cơ sở DT là UTC (mặc dù điều này sẽ là một bước bổ sung cho tất cả mọi người sử dụng cơ sở dữ liệu, và được cho là không có đơn giản hơn chỉ sử dụng UTC thời gian một mình)
iliketocode

2
Có vẻ giống như DateTmeOffset lưu trữ "Thời gian địa phương và Chênh lệch UTC", chứ không phải "Chênh lệch Giờ UTC và UTC". Nếu bạn truyền đến datetime hoặc sử dụng bất kỳ hàm datepart nào, bạn sẽ nhận được các thành phần ngày và giờ cục bộ.
Triynko

" tất cả các khách hàng đều biết giờ UTC của tất cả dữ liệu và cả giờ địa phương ở nơi bắt nguồn thông tin" Mặc dù lưu trữ như một phần của trường ngày tháng cảm thấy không chuẩn hóa trong trường hợp đó. Trường hợp sử dụng là gì - đó là, tại sao bạn không sử dụng UTC & kéo ra bù đắp cho InputLocationId(hoặc thực thể chuẩn hóa tương tự). Sẽ có sự tính toán liên quan (xin chào, ngoại lệ ... đặc biệt là bạn, Indiana ), nhưng nó vẫn là một quá trình xác định - và sau đó sự cân bằng của logic datetime của ứng dụng rất đơn giản.
ruffin

23

Bạn hoàn toàn chính xác khi sử dụng UTC cho tất cả các thời điểm lịch sử (tức là ghi lại các sự kiện đã xảy ra). Luôn có thể đi từ UTC sang giờ địa phương nhưng không phải lúc nào cũng ngược lại.

Khi nào sử dụng giờ địa phương? Trả lời câu hỏi này:

Nếu chính phủ đột ngột quyết định thay đổi mức tiết kiệm ánh sáng ban ngày, bạn có muốn dữ liệu này thay đổi theo không?

Chỉ lưu trữ giờ địa phương nếu câu trả lời là "có". Rõ ràng điều đó sẽ chỉ dành cho những ngày trong tương lai, và thường chỉ dành cho những ngày ảnh hưởng đến mọi người theo một cách nào đó.

Tại sao phải lưu trữ múi giờ / độ lệch?

Thứ nhất, nếu bạn muốn ghi lại mức bù đắp cho người dùng đã thực hiện hành động, bạn có thể chỉ làm điều đó, tức là khi đăng nhập, hãy ghi lại vị trí và múi giờ cho người dùng đó.

Thứ hai, nếu bạn muốn chuyển đổi để hiển thị, bạn cần có một bảng của tất cả các chuyển đổi bù giờ địa phương cho múi giờ đó, chỉ đơn giản biết mức chênh lệch hiện tại là không đủ, bởi vì nếu bạn đang hiển thị ngày / giờ từ sáu tháng trước thì mức chênh lệch sẽ khác biệt.


4
Chuyển đổi UTC sang giờ địa phương của Windows sẽ tính đến thời điểm tiết kiệm ánh sáng ban ngày thay đổi cho các ngày lịch sử. Tôi không hiểu tại sao bạn muốn lưu trữ giờ địa phương trong trường hợp đó.
Jamiegs

1
@Jamiegs Windows chỉ biết về "thông tin lịch sử cuối cùng" trong lịch sử (như được gợi ý / lưu ý trong tài liệu .NET DateTime). Nó không phải là toàn diện.

2
tất nhiên, bạn cũng phải lưu trữ vị trí của sự kiện, nếu không bạn không thể nói những gì "giờ địa phương" sự kiện đã xảy ra.
keuleJ

20

DATETIMEOFFSET cung cấp cho bạn khả năng lưu trữ giờ địa phương và giờ UTC trong một trường.

Điều này cho phép báo cáo rất đơn giản và hiệu quả theo giờ địa phương hoặc UTC mà không cần phải xử lý dữ liệu để hiển thị theo bất kỳ cách nào.

Đây là hai yêu cầu phổ biến nhất - giờ địa phương cho báo cáo địa phương và giờ UTC cho báo cáo nhóm.

Giờ địa phương được lưu trữ trong phần DATETIME của DATETIMEOFFSET và OFFSET từ UTC được lưu trữ trong phần OFFSET, do đó việc chuyển đổi rất đơn giản và vì nó không yêu cầu kiến ​​thức về múi giờ mà dữ liệu đến, tất cả đều có thể được thực hiện ở cấp cơ sở dữ liệu .

Nếu bạn không yêu cầu thời gian xuống đến mili giây, ví dụ chỉ đến phút hoặc giây, bạn có thể sử dụng DATETIMEOFFSET (0). Sau đó, trường DATETIMEOFFSET sẽ chỉ yêu cầu 8 byte dung lượng lưu trữ - giống như DATETIME.

Do đó, việc sử dụng DATETIMEOFFSET thay vì UTC DATETIME mang lại sự linh hoạt, hiệu quả và đơn giản hơn cho việc báo cáo.


Khung thực thể quá tệ không có cách nào để truy cập ngày giờ cục bộ của trường datetimeoffset, khiến không thể truy vấn một ngày cụ thể cục bộ.
Triynko

@Triynko bạn có thể giải thích ý bạn được không? Thí dụ?
reidLinden
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.