Thực hành tốt nhất tiết kiệm thời gian và múi giờ [đóng cửa]


2046

Tôi hy vọng sẽ biến câu hỏi này và câu trả lời cho nó thành hướng dẫn dứt khoát để xử lý thời gian tiết kiệm ánh sáng ban ngày, đặc biệt là để đối phó với sự thay đổi thực tế.

Nếu bạn có bất cứ điều gì để thêm, xin vui lòng làm

Nhiều hệ thống phụ thuộc vào việc giữ thời gian chính xác, vấn đề là thay đổi theo thời gian do tiết kiệm ánh sáng ban ngày - di chuyển đồng hồ tiến hoặc lùi.

Chẳng hạn, người ta có các quy tắc kinh doanh trong một hệ thống nhận đơn hàng phụ thuộc vào thời gian của đơn hàng - nếu đồng hồ thay đổi, các quy tắc có thể không rõ ràng. Làm thế nào để duy trì thời gian của đơn đặt hàng? Tất nhiên có vô số kịch bản - kịch bản này chỉ đơn giản là một kịch bản minh họa.

  • Làm thế nào bạn đã giải quyết vấn đề tiết kiệm ánh sáng ban ngày?
  • Giả định nào là một phần của giải pháp của bạn? (tìm kiếm bối cảnh ở đây)

Điều quan trọng là, nếu không muốn nói là như vậy:

  • Bạn đã thử những gì mà không làm việc?
  • Tại sao nó không hoạt động?

Tôi sẽ quan tâm đến lập trình, hệ điều hành, sự kiên trì dữ liệu và các khía cạnh thích hợp khác của vấn đề.

Câu trả lời chung là tuyệt vời, nhưng tôi cũng muốn xem chi tiết đặc biệt nếu chúng chỉ có sẵn trên một nền tảng.


2
@abatishchev - Cách này GETDATE()trên SQL sẽ là UTC (như ý muốn DateTime.Now). Và máy chủ sẽ không bị ảnh hưởng bởi bất kỳ loại thay đổi DST tự động nào.
Oded

4
@Oded: Tôi có thể đồng ý nếu "trên máy chủ" sẽ được thêm vào. Nhưng điều đó vẫn có thể ảnh hưởng đến các ứng dụng khác cần thời gian địa phương. Bởi lý do này và các lý do khác tôi nghĩ tốt hơn là yêu cầu thời gian Utc rõ ràng.
abatishchev

7
UTC được ưa thích hơn GMT, vì cả hai đều được xác định chính xác hơn và vì định nghĩa GMT bị rối trên một số hệ điều hành. Mọi người thường coi các thuật ngữ "GMT" và "UTC" là có thể hoán đổi cho nhau nhưng chúng không hoàn toàn. Đối với hầu hết mọi mục đích phần mềm / hệ thống, hãy sử dụng UTC. Xem stackoverflow.com/questions/2292334/ Mạnh
Chris Johnson

7
@JoshStodola - ' câu trả lời ' của Jon Skeet .
Kenny Evitt

1
@Oded bạn không thể cho rằng máy chủ sẽ ở trên UTC, tôi đã thấy các máy chủ sản xuất trong đó múi giờ là "UTC" nhưng đã áp dụng DST nên thực sự là UTC + 1 trong hơn nửa năm. Đồng ý với @abatishchev là rõ ràng và sử dụng DateTime.UtcNow, và GETUTCDATE()nó cũng cho thấy các nhà phát triển khác mà bạn thực sự nghĩ về nó
ono2012

Câu trả lời:


940

Tóm tắt câu trả lời và dữ liệu khác: (vui lòng thêm của bạn)

Làm:

  • Bất cứ khi nào bạn đang đề cập đến một thời điểm chính xác, hãy duy trì thời gian theo một tiêu chuẩn thống nhất không bị ảnh hưởng bởi tiết kiệm ánh sáng ban ngày. (GMT và UTC tương đương với vấn đề này, nhưng nên sử dụng thuật ngữ UTC. Lưu ý rằng UTC còn được gọi là thời gian Zulu hoặc Z. )
  • Thay vào đó, nếu bạn chọn duy trì thời gian bằng cách sử dụng giá trị thời gian cục bộ, hãy bao gồm bù thời gian cục bộ cho thời gian cụ thể này từ UTC (phần bù này có thể thay đổi trong suốt cả năm), do đó dấu thời gian sau đó có thể được giải thích rõ ràng.
  • Trong một số trường hợp, bạn có thể cần lưu trữ cả thời gian UTC và thời gian địa phương tương đương. Thông thường điều này được thực hiện với hai trường riêng biệt, nhưng một số nền tảng hỗ trợ một datetimeoffsetloại có thể lưu trữ cả hai trong một trường duy nhất.
  • Khi lưu trữ dấu thời gian dưới dạng giá trị số, hãy sử dụng thời gian Unix - là số giây toàn bộ kể từ 1970-01-01T00:00:00Z(không tính giây nhuận). Nếu bạn yêu cầu độ chính xác cao hơn, hãy sử dụng mili giây thay thế. Giá trị này phải luôn dựa trên UTC, không có bất kỳ điều chỉnh múi giờ nào.
  • Nếu sau này bạn có thể cần sửa đổi dấu thời gian, hãy bao gồm ID múi giờ ban đầu để bạn có thể xác định xem phần bù có thể thay đổi so với giá trị ban đầu được ghi hay không.
  • Khi lên lịch các sự kiện trong tương lai, thông thường giờ địa phương được ưu tiên thay vì UTC, vì thông thường, phần bù sẽ thay đổi. Xem câu trả lời , và bài viết trên blog .
  • Khi lưu trữ toàn bộ ngày, chẳng hạn như sinh nhật và ngày kỷ niệm, không chuyển đổi sang UTC hoặc bất kỳ múi giờ nào khác.
    • Khi có thể, lưu trữ trong một loại dữ liệu chỉ có ngày không bao gồm thời gian trong ngày.
    • Nếu loại như vậy không có sẵn, hãy chắc chắn luôn luôn bỏ qua thời gian trong ngày khi diễn giải giá trị. Nếu bạn không thể yên tâm rằng thời gian trong ngày sẽ bị bỏ qua, hãy chọn 12:00 trưa, thay vì 00:00 Nửa đêm là thời gian đại diện an toàn hơn vào ngày đó.
  • Hãy nhớ rằng độ lệch múi giờ không phải luôn luôn là số giờ nguyên (ví dụ: Giờ chuẩn Ấn Độ là UTC + 05: 30 và Nepal sử dụng UTC + 05: 45).
  • Nếu sử dụng Java, hãy sử dụng java.time cho Java 8 trở lên.
  • Nếu sử dụng .NET , hãy cân nhắc sử dụng Noda Time .
  • Nếu sử dụng .NET mà không có Noda Time, hãy xem xét đó DateTimeOffsetthường là lựa chọn tốt hơn DateTime.
  • Nếu sử dụng Perl, hãy sử dụng DateTime .
  • Nếu sử dụng Python, hãy sử dụng pytz hoặc dateutil .
  • Nếu sử dụng JavaScript, hãy sử dụng khoảnh khắc.js với tiện ích mở rộng múi giờ .
  • Nếu sử dụng PHP> 5.2, hãy sử dụng các chuyển đổi múi giờ riêng được cung cấp bởi DateTimeDateTimeZonecác lớp. Hãy cẩn thận khi sử dụng DateTimeZone::listAbbreviations()- xem câu trả lời . Để giữ cho PHP với cập nhật dữ liệu Olson, cài đặt định kỳ các timezonedb gói PECL; xem câu trả lời .
  • Nếu sử dụng C ++, hãy chắc chắn sử dụng thư viện sử dụng đúng cơ sở dữ liệu múi giờ IANA . Chúng bao gồm thư viện "tz" của cctz , ICUHoward Hinnant .
    • Không sử dụng Boost cho chuyển đổi múi giờ. Mặc dù API của nó tuyên bố hỗ trợ các số nhận dạng IANA tiêu chuẩn (còn gọi là "khu vực thông tin"), nhưng nó ánh xạ thô sơ chúng vào dữ liệu theo kiểu POSIX, mà không xem xét lịch sử thay đổi phong phú của từng khu vực. (Ngoài ra, các tập tin đã rơi ra khỏi bảo trì.)
  • Nếu sử dụng Rust, sử dụng chrono .
  • Hầu hết các quy tắc kinh doanh sử dụng thời gian dân sự, thay vì UTC hoặc GMT. Do đó, hãy lên kế hoạch chuyển đổi dấu thời gian UTC sang múi giờ địa phương trước khi áp dụng logic ứng dụng.
  • Hãy nhớ rằng múi giờ và độ lệch không cố định và có thể thay đổi. Chẳng hạn, trong lịch sử Hoa Kỳ và Vương quốc Anh đã sử dụng cùng một ngày để 'hồi xuân' và 'quay lại'. Tuy nhiên, vào năm 2007, Hoa Kỳ đã thay đổi ngày mà đồng hồ được thay đổi. Điều này bây giờ có nghĩa là trong 48 tuần trong năm, sự khác biệt giữa giờ Luân Đôn và giờ New York là 5 giờ và trong 4 tuần (3 vào mùa xuân, 1 vào mùa thu) là 4 giờ. Hãy nhận biết các mục như thế này trong bất kỳ tính toán nào liên quan đến nhiều khu vực.
  • Xem xét loại thời gian (thời gian sự kiện thực tế, thời gian phát sóng, thời gian tương đối, thời gian lịch sử, thời gian định kỳ) những yếu tố nào (dấu thời gian, độ lệch múi giờ và tên múi giờ) bạn cần lưu trữ để truy xuất chính xác - xem "Loại thời gian" trong Câu trả lời này .
  • Giữ các tệp tzdata của hệ điều hành, cơ sở dữ liệu và ứng dụng của bạn đồng bộ, giữa chúng và phần còn lại của thế giới.
  • Trên máy chủ, đặt đồng hồ phần cứng và đồng hồ hệ điều hành thành UTC thay vì múi giờ địa phương.
  • Bất kể điểm đầu dòng trước đó, mã phía máy chủ, bao gồm các trang web, không bao giờ nên mong đợi múi giờ địa phương của máy chủ là bất cứ điều gì cụ thể. xem câu trả lời .
  • Thích làm việc với các múi giờ trên cơ sở từng trường hợp trong mã ứng dụng của bạn, thay vì toàn cầu thông qua cài đặt tệp cấu hình hoặc mặc định.
  • Sử dụng dịch vụ NTP trên tất cả các máy chủ.
  • Nếu sử dụng FAT32 , hãy nhớ rằng dấu thời gian được lưu trữ theo giờ địa phương, không phải UTC.
  • Khi xử lý các sự kiện định kỳ (ví dụ: chương trình truyền hình hàng tuần), hãy nhớ rằng thời gian thay đổi với DST và sẽ khác nhau theo các múi giờ.
  • Luôn truy vấn các giá trị thời gian theo ngày bao gồm giới hạn dưới, bao gồm giới hạn trên ( >=, <).

Đừng:

  • Đừng nhầm lẫn giữa "múi giờ", chẳng hạn như America/New_York"bù múi giờ", chẳng hạn như -05:00. Họ là hai việc khác nhau. Xem wiki thẻ thời gian .
  • Không sử dụng Dateđối tượng JavaScript để thực hiện tính toán ngày và giờ trong các trình duyệt web cũ hơn, vì ECMAScript 5.1 trở xuống có lỗi thiết kế có thể sử dụng thời gian tiết kiệm ánh sáng ban ngày không chính xác. (Điều này đã được sửa trong ECMAScript 6/2015).
  • Không bao giờ tin tưởng đồng hồ của khách hàng. Nó rất có thể không chính xác.
  • Đừng nói với mọi người rằng "luôn luôn sử dụng UTC ở mọi nơi". Lời khuyên rộng rãi này được xem xét ngắn gọn về một số tình huống hợp lệ được mô tả trước đó trong tài liệu này. Thay vào đó, hãy sử dụng tham chiếu thời gian thích hợp cho dữ liệu bạn đang làm việc. ( Dấu thời gian có thể sử dụng UTC, nhưng không nên lập lịch thời gian và giá trị chỉ trong ngày trong tương lai.)

Kiểm tra:

  • Khi kiểm tra, hãy đảm bảo bạn kiểm tra các quốc gia ở bán cầu Tây, Đông, Bắc và Nam (thực tế ở mỗi quý trên toàn cầu, vì vậy 4 khu vực), với cả DST đang tiến hành và không (cho 8), và một quốc gia thực hiện không sử dụng DST (4 cái khác để bao gồm tất cả các vùng, tổng cộng là 12).
  • Kiểm tra quá trình chuyển đổi của DST, tức là khi bạn đang trong thời gian mùa hè, chọn giá trị thời gian từ mùa đông.
  • Kiểm tra các trường hợp ranh giới, chẳng hạn như múi giờ là UTC + 12, với DST, làm cho giờ địa phương UTC + 13 vào mùa hè và thậm chí các địa điểm là UTC + 13 vào mùa đông
  • Kiểm tra tất cả các thư viện và ứng dụng của bên thứ ba và đảm bảo rằng họ xử lý dữ liệu múi giờ chính xác.
  • Kiểm tra múi giờ nửa giờ, ít nhất.

Tài liệu tham khảo:

Khác:

  • Vận động đại diện của bạn để kết thúc sự ghê tởm đó là DST. Chúng ta luôn có thể hy vọng ...
  • Tiền sảnh cho giờ chuẩn trái đất

31
Sử dụng giờ GMT không thực sự giải quyết vấn đề, bạn vẫn cần phải tìm ra những gì các đồng bằng quyền áp dụng là, và đây là nơi mà tất cả những điều dối trá phức tạp. Đồng bằng có thể phức tạp để xác định trong các hệ thống được người dùng sử dụng ở các khu vực khác nhau (với lịch chuyển đổi tiết kiệm ánh sáng ban ngày khác nhau) hoặc trong các hệ thống hiển thị dữ liệu lịch sử / tương lai.
ckhras

10
Điều đó đúng nếu tất cả các ứng dụng cần làm là hiển thị giờ địa phương hiện tại. Nhưng nếu chúng ta có một máy chủ ở Úc cần hiển thị ngày / giờ cho giao dịch ở Canada vào ngày 2 tháng 4 năm 2006 (Đây là năm cuối cùng trước khi quy tắc chuyển đổi tiết kiệm ánh sáng ban ngày thay đổi ở Canada) - bạn có gọi cho hệ điều hành không có thể thực hiện DateTime ("2006/04/02 14: 35Z"). ToLocalTime (). WithDaylightSavingRules ("Canada", 2006)?
ckhras

22
Có, có một cuộc gọi HĐH như vậy trong Windows - SystemTimeToTzSpecificLocation. msdn.microsoft.com/en-us/l Library / ms724949 (VS85) .aspx
Michael Madsen

7
@tchrist Có lẽ nếu bạn kiên trì thì bạn có thể.
Peter Ajtai

16
Hãy nhớ chuyển đổi ngày trong tương lai (thậm chí chỉ ngày mai) sang UTC bạn luôn mất thứ gì đó. Ví dụ: bạn đã sử dụng một số bù đã biết để thực hiện chuyển đổi đó, nhưng vì ngày đó là trong tương lai, nên luôn có khả năng nhóm đặt các quy tắc đó sẽ thay đổi các quy tắc đó. Ngoài ra, hầu như không thể chuyển đổi một số ngày trong tương lai sang UTC vì thời gian tiết kiệm ánh sáng ban ngày không được biết cho đến năm đó (một số quốc gia đặt ngày hàng năm, không phải trước 10 năm hoặc dựa trên bất kỳ quy tắc nào được đặt ra).
eselk

319

Tôi không chắc những gì tôi có thể thêm vào các câu trả lời ở trên, nhưng đây là một vài điểm từ tôi:

Các loại thời gian

Có bốn thời điểm khác nhau bạn nên xem xét:

  1. Thời gian sự kiện: ví dụ: thời gian xảy ra sự kiện thể thao quốc tế hoặc đăng quang / tử vong / v.v. Điều này phụ thuộc vào múi giờ của sự kiện chứ không phải của người xem.
  2. Giờ truyền hình: ví dụ, một chương trình truyền hình cụ thể được phát vào lúc 9 giờ tối giờ địa phương trên toàn thế giới. Quan trọng khi suy nghĩ về việc công bố kết quả (nói American Idol) trên trang web của bạn
  3. Thời gian tương đối: ví dụ: Câu hỏi này có kết thúc mở tiền thưởng trong 21 giờ. Điều này rất dễ hiển thị
  4. Thời gian định kỳ: ví dụ: Một chương trình truyền hình vào mỗi thứ Hai lúc 9 giờ tối, ngay cả khi DST thay đổi.

Ngoài ra còn có lịch sử / thời gian thay thế. Đây là những phiền toái bởi vì họ có thể không ánh xạ trở lại thời gian tiêu chuẩn. Ví dụ: ngày Julian, ngày theo lịch âm trên sao Thổ, lịch Klingon.

Lưu trữ dấu thời gian bắt đầu / kết thúc trong UTC hoạt động tốt. Đối với 1, bạn cần một tên múi giờ sự kiện + phần bù được lưu trữ cùng với sự kiện. Đối với 2, bạn cần một số nhận dạng thời gian cục bộ được lưu trữ với từng vùng và tên múi giờ địa phương + phần bù được lưu trữ cho mọi người xem (có thể lấy thông tin này từ IP nếu bạn đang ở trạng thái khủng hoảng). Trong 3, lưu trữ trong UTC giây và không cần múi giờ. 4 là trường hợp đặc biệt 1 hoặc 2 tùy thuộc vào việc đó là sự kiện toàn cầu hay địa phương, nhưng bạn cũng cần lưu trữ một dấu thời gian được tạo để bạn có thể biết liệu định nghĩa múi giờ đã thay đổi trước hay sau khi sự kiện này được tạo. Điều này là cần thiết nếu bạn cần hiển thị dữ liệu lịch sử.

Thời gian lưu trữ

  • Luôn lưu trữ thời gian trong UTC
  • Chuyển đổi thành giờ địa phương trên màn hình (cục bộ được xác định bởi người dùng đang xem dữ liệu)
  • Khi lưu trữ múi giờ, bạn cần tên, dấu thời gian và phần bù. Điều này là bắt buộc vì đôi khi chính phủ thay đổi ý nghĩa của múi giờ của họ (ví dụ: chính phủ Hoa Kỳ đã thay đổi ngày DST) và ứng dụng của bạn cần xử lý mọi thứ một cách duyên dáng ... ví dụ: Dấu thời gian chính xác khi các tập LOST hiển thị cả trước và sau quy tắc DST đã thay đổi

Offsets và tên

Một ví dụ về những điều trên sẽ là:

Trận chung kết cúp bóng đá thế giới đã diễn ra ở Nam Phi (UTC + 2 - SAST) vào ngày 11 tháng 7 năm 2010 lúc 19:00 UTC.

Với thông tin này, về mặt lịch sử, chúng ta có thể xác định thời gian chính xác khi trận chung kết WCS 2010 diễn ra ngay cả khi định nghĩa múi giờ của Nam Phi thay đổi có thể hiển thị cho người xem theo múi giờ địa phương của họ tại thời điểm họ truy vấn cơ sở dữ liệu.

Giờ hệ thống

Bạn cũng cần giữ đồng bộ các tệp tzdata của hệ điều hành, cơ sở dữ liệu và ứng dụng của mình, cả với nhau và với phần còn lại của thế giới và kiểm tra rộng rãi khi bạn nâng cấp. Không có gì lạ khi ứng dụng của bên thứ ba mà bạn phụ thuộc không xử lý thay đổi TZ một cách chính xác.

Đảm bảo đồng hồ phần cứng được đặt thành UTC và nếu bạn đang chạy các máy chủ trên toàn thế giới, hãy đảm bảo rằng các hệ điều hành của chúng cũng được cấu hình để sử dụng UTC. Điều này trở nên rõ ràng khi bạn cần sao chép các tệp nhật ký apache được xoay hàng giờ từ các máy chủ trong nhiều múi giờ. Sắp xếp chúng theo tên tệp chỉ hoạt động nếu tất cả các tệp được đặt tên với cùng múi giờ. Điều đó cũng có nghĩa là bạn không phải làm toán ngày trong đầu khi bạn ssh từ hộp này sang hộp khác và cần so sánh dấu thời gian.

Ngoài ra, chạy ntpd trên tất cả các hộp.

Khách hàng

Không bao giờ tin vào dấu thời gian bạn nhận được từ máy khách là hợp lệ. Ví dụ: tiêu đề Ngày: HTTP hoặc Date.getTime()cuộc gọi javascript . Chúng tốt khi được sử dụng làm định danh mờ hoặc khi thực hiện toán ngày trong một phiên duy nhất trên cùng một máy khách, nhưng đừng cố tham chiếu chéo các giá trị này với thứ bạn có trên máy chủ. Khách hàng của bạn không chạy NTP và có thể không nhất thiết phải có pin hoạt động cho đồng hồ BIOS của họ.

Câu đố

Cuối cùng, chính phủ đôi khi sẽ làm những điều rất kỳ lạ:

Thời gian tiêu chuẩn ở Hà Lan là chính xác 19 phút và 32,13 giây trước UTC theo luật từ 1909-05-01 đến 1937-06-30. Múi giờ này không thể được biểu diễn chính xác bằng định dạng HH: MM.

Ok, tôi nghĩ tôi đã xong.


6
Câu trả lời này có một số điểm tuyệt vời, tôi đặc biệt muốn chỉ ra phần này "Thời gian định kỳ: ví dụ: Một chương trình TV vào mỗi thứ Hai lúc 9 giờ tối, ngay cả khi DST thay đổi" Lưu trữ thời gian trong UTC trong DB và sau đó chuyển đổi để hiển thị giúp xử lý rất nhiều khía cạnh khó khăn trong việc xử lý các múi giờ. Tuy nhiên, việc xử lý "các sự kiện định kỳ" vượt qua các rào cản DST trở nên khó khăn hơn nhiều.
Jared Hales

45
+1 cho các câu đố. Giữ cho nội dung thú vị làm cho nhiệm vụ này thú vị hơn, điều này có thể dẫn đến tăng năng suất :)
Chris

4
Rất nhiều thứ tốt trong câu trả lời này, nhưng một vài vấn đề. 1) Nhiều chữ viết tắt múi giờ là mơ hồ. xem ở đây 2) Không phải lúc nào bạn cũng muốn lưu trữ trong UTC. Hầu hết thời gian - có, nhưng vấn đề bối cảnh. Theo thuật ngữ của bạn, thời gian truyền hình sẽ không được lưu trữ trong UTC. Ngoài ra, đôi khi chính sách bất hợp pháp hoặc chống lại chính sách không lưu trữ giờ địa phương - đó là nơi mà những thứ như DateTimeOffset(hoặc tương đương) có ích. Nếu không, tốt viết lên.
Matt Johnson-Pint

1
Vì vậy, mọi người đều đồng ý rằng thư viện Joda cho đến nay là công cụ tốt nhất có sẵn cho công việc. Tuy nhiên, chúng tôi cần tiếp tục cập nhật (xây dựng lại) tệp jar JODA theo bài viết này ( joda.org/joda-time/tz_update.html ) để cập nhật thông tin múi giờ mới nhất. Có cách nào để tải xuống dữ liệu múi giờ mới nhất từ ​​trang web IANA ( iana.org/time-zones ) và xây dựng lại thư viện joda không? Nói cách khác, có thể tự động hóa quá trình này thay vì thực hiện thủ công?
saravana_pc

2
Hà Lan đố có vẻ hợp pháp. ietf.org/rfc/rfc3339.txt phần 5.8. Nửa chừng hình dung ai đó đang kéo chân chúng tôi.
ruffin

89

Đây là một vấn đề quan trọng và đáng ngạc nhiên khó khăn. Sự thật là không có tiêu chuẩn hoàn toàn thỏa mãn cho thời gian bền bỉ. Ví dụ, tiêu chuẩn SQL và định dạng ISO (ISO 8601) rõ ràng là không đủ.

Từ quan điểm khái niệm, người ta thường xử lý hai loại dữ liệu thời gian và rất thuận tiện để phân biệt chúng (các tiêu chuẩn trên không): " thời gian thực " và " thời gian dân sự ".

Một thời gian "vật lý" là một điểm trong dòng thời gian phổ quát liên tục mà vật lý đối phó (tất nhiên bỏ qua tính tương đối). Ví dụ, khái niệm này có thể được mã hóa đầy đủ trong UTC (nếu bạn có thể bỏ qua giây nhuận).

Thời gian "dân sự" là một đặc tả thời gian theo các chỉ tiêu dân sự: một điểm thời gian ở đây được chỉ định đầy đủ bởi một tập các trường thời gian (Y, M, D, H, MM, S, FS) cộng với TZ (đặc tả múi giờ) (thực ra cũng là "lịch", nhưng giả sử chúng ta hạn chế thảo luận về lịch Gregorian). Một múi giờ và lịch cùng cho phép (về nguyên tắc) ánh xạ từ đại diện này sang đại diện khác. Nhưng các yếu tố thời gian dân sự và vật lý là các loại cường độ khác nhau về cơ bản, và chúng nên được giữ tách biệt về mặt khái niệm và đối xử khác nhau (một dạng tương tự: mảng byte và chuỗi ký tự).

Vấn đề là khó hiểu bởi vì chúng ta nói về các loại sự kiện này thay thế cho nhau, và bởi vì thời gian dân sự có thể thay đổi chính trị. Vấn đề (và sự cần thiết phải phân biệt các khái niệm này) trở nên rõ ràng hơn cho các sự kiện trong tương lai. Ví dụ (lấy từ cuộc thảo luận của tôi ở đây .

John ghi lại trong lịch của mình một lời nhắc cho một số sự kiện tại datetime 2019-Jul-27, 10:30:00, TZ = Chile/Santiago, (đã bù GMT-4, do đó nó tương ứng với UTC 2019-Jul-27 14:30:00). Nhưng một ngày nào đó trong tương lai, quốc gia này quyết định thay đổi bù TZ thành GMT-5.

Bây giờ, khi ngày đến ... nên nhắc nhở đó kích hoạt tại

A) 2019-Jul-27 10:30:00 Chile/Santiago = UTC time 2019-Jul-27 15:30:00?

hoặc là

B) 2019-Jul-27 9:30:00 Chile/Santiago = UTC time 2019-Jul-27 14:30:00?

Không có câu trả lời chính xác, trừ khi người ta biết ý nghĩa của John khi nói với lịch "Xin hãy gọi cho tôi tại 2019-Jul-27, 10:30:00 TZ=Chile/Santiago".

Có phải anh ta có nghĩa là "thời gian dân sự" ("khi đồng hồ trong thành phố của tôi nói 10:30")? Trong trường hợp đó, A) là câu trả lời đúng.

Hay ông có nghĩa là "tức thời vật lý", một điểm trong dòng thời gian tiếp diễn của vũ trụ chúng ta, nói, "khi nhật thực tiếp theo xảy ra". Trong trường hợp đó, câu B) là câu đúng.

Một vài API Ngày / Giờ có được sự khác biệt này: trong số đó, Jodatime , là nền tảng của API DateTime Java (thứ ba!) Tiếp theo (JSR 310).


1
Một điểm khác để xem xét mà tôi chưa thấy địa chỉ trong API là ngay cả khi thời gian và múi giờ được đưa ra, có ít nhất hai ý nghĩa chính đáng cho ví dụ: "13: 00: 00EDT". Nó có thể được đề cập đến một cái gì đó được biết là xảy ra vào lúc 1 giờ chiều giờ địa phương, được cho là vào Giờ ban ngày miền Đông, hoặc một cái gì đó được biết là đã xảy ra vào thời điểm Đông phương bắt đầu lúc 13:00, được cho là đã xảy ra ở một nơi quan sát Giờ ban ngày miền Đông. Nếu một người có nhiều dấu thời gian trong đó thông tin múi giờ có thể sai (ví dụ: tệp máy ảnh kỹ thuật số) ...
supercat

1
... Việc biết liệu chúng phản ánh thời gian địa phương chính xác hay thời gian toàn cầu có thể quan trọng trong việc xác định cách sửa chúng.
supercat

3
Rõ ràng John muốn A) vì mọi người đi làm lúc 8:30, bất kể DST hay múi giờ hiện tại là gì. Nếu họ đi vào DST, họ sẽ đi làm lúc 8:30, khi họ rời khỏi DST, họ sẽ đi làm lúc 8:30. Nếu quốc gia quyết định chuyển sang múi giờ khác, họ sẽ đi làm vào lúc 8:30 ngày
Gianluca Ghettini

59

Phân tách rõ ràng các mối quan tâm về kiến ​​trúc - để biết chính xác tầng nào tương tác với người dùng và phải thay đổi thời gian ngày cho / từ biểu diễn chính tắc (UTC). Thời gian không phải là UTC là thời gian trình bày (theo múi giờ địa phương của người dùng), thời gian UTC là mô hình (vẫn là duy nhất cho tầng sau và tầng giữa).

Ngoài ra, hãy quyết định đối tượng thực sự của bạn là gì, những gì bạn không phải phục vụ và nơi bạn vẽ đường . Đừng chạm vào lịch ngoại trừ khi bạn thực sự có khách hàng quan trọng ở đó và sau đó xem xét (các) máy chủ đối diện người dùng riêng biệt chỉ dành cho khu vực đó.

Nếu bạn có thể có được và duy trì vị trí của người dùng, hãy sử dụng vị trí để chuyển đổi thời gian theo ngày có hệ thống (giả sử văn hóa .NET hoặc bảng SQL) nhưng cung cấp cách để người dùng cuối chọn ghi đè nếu thời gian ngày là quan trọng đối với người dùng của bạn.

Nếu có các nghĩa vụ kiểm toán lịch sử liên quan (như nói chính xác khi Jo ở AZ thanh toán hóa đơn 2 năm trước vào tháng 9) thì hãy giữ cả UTC và giờ địa phương cho hồ sơ (bảng chuyển đổi của bạn sẽ thay đổi theo thời gian).

Xác định múi giờ tham chiếu thời gian cho dữ liệu xuất hiện hàng loạt - như các tệp, dịch vụ web, v.v. Công ty Say East Coast có trung tâm dữ liệu trong CA - bạn cần hỏi và biết những gì họ sử dụng làm tiêu chuẩn thay vì giả sử cái này hay cái khác.

Không tin tưởng các độ lệch múi giờ được nhúng trong biểu diễn văn bản của thời gian và không chấp nhận phân tích và theo dõi chúng. Thay vào đó luôn luôn yêu cầu rằng múi giờ và / hoặc vùng tham chiếu phải được xác định rõ ràng . Bạn có thể dễ dàng nhận được thời gian với bù PST nhưng thời gian thực sự là EST vì đó là thời gian tham chiếu và hồ sơ của khách hàng vừa được xuất tại một máy chủ ở PST.


40

Bạn cần biết về cơ sở dữ liệu Olson tz , có sẵn từ ftp://elsie.nci.nih.gov/pub http://iana.org/time-zones/ . Nó được cập nhật nhiều lần mỗi năm để đối phó với những thay đổi thường xảy ra vào phút cuối khi (và liệu) chuyển đổi giữa thời gian mùa đông và mùa hè (tiết kiệm ánh sáng tiêu chuẩn và ánh sáng ban ngày) ở các quốc gia khác nhau trên thế giới. Trong năm 2009, bản phát hành cuối cùng là năm 2009; năm 2010 là 2010n; năm 2011 là 2011n; vào cuối tháng 5 năm 2012, bản phát hành là 2012c. Lưu ý rằng có một bộ mã để quản lý dữ liệu và dữ liệu múi giờ thực tế, trong hai kho lưu trữ riêng biệt (tzcode20xxy.tar.gz và tzdata20xxy.tar.gz). Cả mã và dữ liệu đều thuộc phạm vi công cộng.

Đây là nguồn gốc của các tên múi giờ như America / Los_Angele (và các từ đồng nghĩa như US / Pacific).

Nếu bạn cần theo dõi các khu vực khác nhau, thì bạn cần cơ sở dữ liệu Olson. Như những người khác đã khuyên, bạn cũng muốn lưu trữ dữ liệu ở định dạng cố định - UTC thường là dữ liệu được chọn - cùng với bản ghi về múi giờ nơi dữ liệu được tạo. Bạn có thể muốn phân biệt giữa phần bù với UTC tại thời điểm và tên múi giờ; Điều đó có thể tạo ra sự khác biệt sau này. Ngoài ra, biết rằng hiện tại là 2010 / 03-28T23: 47: 00-07: 00 (Hoa Kỳ / Thái Bình Dương) có thể hoặc không thể giúp bạn diễn giải giá trị 2010-11-15T12: 30 - có lẽ được chỉ định trong PST ( Giờ chuẩn Thái Bình Dương) thay vì PDT (Giờ tiết kiệm ánh sáng ban ngày Thái Bình Dương).

Các giao diện thư viện C tiêu chuẩn không hữu ích lắm với loại công cụ này.


Dữ liệu của Olson đã bị di chuyển, một phần vì AD Olson sẽ nghỉ hưu sớm, và một phần vì đã có một vụ kiện pháp lý (hiện đã bị bãi bỏ) đối với những người bảo trì vì vi phạm bản quyền. Cơ sở dữ liệu múi giờ hiện được quản lý dưới sự bảo trợ của IANA , Cơ quan cấp số được gán Internet và có một liên kết trên trang nhất tới 'Cơ sở dữ liệu múi giờ ' . Danh sách gửi thư thảo luận là bây giờ tz@iana.org; danh sách thông báo là tz-announce@iana.org.


12
Cơ sở dữ liệu Olson cũng chứa dữ liệu lịch sử , điều này làm cho nó đặc biệt hữu ích để xử lý DST. Ví dụ, nó biết rằng giá trị UTC tương ứng với ngày 31 tháng 3 năm 2000 ở Hoa Kỳ không nằm trong DST, mà là giá trị UTC tương ứng với ngày 31 tháng 3 năm 2008 tại Hoa Kỳ.
Josh Kelley

3
Unicode Consortium duy trì ánh xạ giữa ID khu vực của Olson và ID múi giờ của Windows: unicode.org/repose/cldr-tmp/trunk/diff/supcellenceal/ trộm
Josh Kelley 29:00

Liên kết được cập nhật cho trang của Hiệp hội Unicode: unicode.org/repose/cldr-tmp/trunk/diff/sup THỰCal / Lỗi
Span

Nơi nào người ta có thể tìm thấy thông tin về phân tích tệp Olson? Tôi muốn biên dịch nó thành một bảng db, nhưng không thể hiểu làm thế nào tôi nên đọc các tệp
shealtiel

@gidireich: thông tin chính được tìm thấy cùng với dữ liệu và không dễ hiểu. Tài liệu chính cho nó là trong zic.8trang man (hoặc zic.8.txt). Bạn sẽ cần tzcode2011i.tar.gztệp chứ không phải, hoặc cũng như tzdata2011i.tar.gztệp để có được thông tin này.
Jonathan Leffler

26

Nói chung, bao gồm bù thời gian cục bộ (bao gồm bù DST) trong dấu thời gian được lưu trữ: Chỉ riêng UTC là không đủ nếu sau này bạn muốn hiển thị dấu thời gian trong múi giờ gốc (và cài đặt DST).

Hãy nhớ rằng phần bù không phải luôn luôn là số giờ nguyên (ví dụ Giờ ​​chuẩn của Ấn Độ là UTC + 05: 30).

Ví dụ: các định dạng phù hợp là một tuple (thời gian unix, bù theo phút) hoặc ISO 8601 .


5
Để hiển thị, phần bù là hoàn hảo. Nếu bạn muốn thực hiện thay đổi, phần bù vẫn chưa đủ. Bạn cũng phải biết múi giờ vì giá trị mới có thể yêu cầu bù khác.
Matt Johnson-Pint

23

Vượt qua ranh giới của "thời gian máy tính" và "thời gian của con người" là một cơn ác mộng. Cái chính là không có tiêu chuẩn nào cho các quy tắc chi phối các múi giờ và thời gian tiết kiệm ánh sáng ban ngày. Các quốc gia có thể tự do thay đổi quy tắc múi giờ và DST của họ bất cứ lúc nào và họ cũng vậy.

Một số quốc gia, ví dụ như Israel, Brazil, quyết định mỗi năm sẽ có thời gian tiết kiệm ánh sáng ban ngày của họ, vì vậy không thể biết trước khi nào (nếu) DST sẽ có hiệu lực. Những người khác có các quy tắc (ish) cố định khi DST có hiệu lực. Các quốc gia khác không sử dụng DST như tất cả.

Các múi giờ không phải chênh lệch toàn giờ so với GMT. Nepal là +5,45. Thậm chí có những múi giờ là +13. Đó có nghĩa là:

SUN 23:00 in Howland Island (-12)
MON 11:00 GMT 
TUE 00:00 in Tonga (+13)

Tất cả đều giống nhau, nhưng 3 ngày khác nhau!

Cũng không có tiêu chuẩn rõ ràng về các chữ viết tắt cho múi giờ và cách chúng thay đổi khi ở DST để bạn kết thúc với những thứ như thế này:

AST Arab Standard Time     UTC+03
AST Arabian Standard Time  UTC+04
AST Arabic Standard Time   UTC+03

Lời khuyên tốt nhất là tránh xa thời gian địa phương càng nhiều càng tốt và bám vào UTC nơi bạn có thể. Chỉ chuyển đổi sang giờ địa phương tại thời điểm cuối cùng có thể.

Khi kiểm tra, đảm bảo bạn kiểm tra các quốc gia ở bán cầu Tây và Đông, với cả DST đang tiến hành và không và một quốc gia không sử dụng DST (tổng cộng 6).


Về Israel - điều này đúng một nửa. Mặc dù thời gian thay đổi DST không phải là một ngày cụ thể trong lịch Julian - có một quy tắc dựa trên lịch Do Thái (có một thay đổi vào năm 2014). Dù sao, ý tưởng chung là chính xác - những điều này có thể và thay đổi một lần trong một thời gian
Yaron U.

1
Ngoài ra, AST = Giờ chuẩn Đại Tây Dương. Đối với 'lời khuyên tốt nhất', đây là điểm khởi đầu ổn, nhưng bạn cần đọc phần còn lại của trang này và nói một lời cầu nguyện nhỏ, và bạn có thể hiểu ngay sau đó.
DavidWalley

20

Đối với PHP:

Lớp DateTimeZone trong PHP> 5.2 đã dựa trên Olson DB mà người khác đề cập, vì vậy nếu bạn đang thực hiện chuyển đổi múi giờ trong PHP và không phải trong DB, bạn được miễn làm việc với các tệp Olson (khó hiểu).

Tuy nhiên, PHP không được cập nhật thường xuyên như Olson DB, vì vậy chỉ cần sử dụng chuyển đổi múi giờ của PHP có thể khiến bạn có thông tin DST lỗi thời và ảnh hưởng đến tính chính xác của dữ liệu của bạn. Mặc dù điều này không được dự kiến ​​sẽ xảy ra thường xuyên, nhưng nó có thể xảy ra và sẽ xảy ra nếu bạn có một lượng lớn người dùng trên toàn thế giới.

Để đối phó với vấn đề trên, hãy sử dụng gói pecl timezencedb . Chức năng của nó là cập nhật dữ liệu múi giờ của PHP. Cài đặt gói này thường xuyên như được cập nhật. (Tôi không chắc các bản cập nhật cho gói này có tuân theo chính xác các bản cập nhật của Olson hay không, nhưng dường như nó được cập nhật ở tần số ít nhất là rất gần với tần suất cập nhật của Olson.)


18

Nếu thiết kế của bạn có thể chứa nó, hãy tránh chuyển đổi thời gian cục bộ cùng nhau!

Tôi biết một số điều này nghe có vẻ điên rồ nhưng hãy nghĩ về UX: người dùng xử lý gần, ngày tương đối (hôm nay, hôm qua, thứ Hai tuần sau) nhanh hơn so với ngày tuyệt đối (2010/09/17, thứ Sáu ngày 17 tháng 9) trong nháy mắt. Và khi bạn nghĩ về nó nhiều hơn, độ chính xác của múi giờ (và DST) càng quan trọng thì ngày càng gần now(), vì vậy nếu bạn có thể biểu thị ngày / thời gian theo định dạng tương đối trong +/- 1 hoặc 2 tuần, phần còn lại của ngày có thể là UTC và nó không quá quan trọng đối với 95% người dùng.

Bằng cách này, bạn có thể lưu trữ tất cả các ngày trong UTC và so sánh tương đối trong UTC và chỉ cần hiển thị ngày UTC của người dùng bên ngoài Ngưỡng ngày tương đối của bạn.

Điều này cũng có thể áp dụng cho đầu vào của người dùng (nhưng nói chung là trong một giới hạn hơn). Việc chọn từ một danh sách thả xuống chỉ có {Hôm qua, Hôm nay, Ngày mai, Thứ hai tuần sau, Thứ năm tới} rất đơn giản và dễ dàng hơn cho người dùng so với công cụ chọn ngày. Bộ chọn ngày là một trong những thành phần gây đau đớn nhất của điền vào mẫu. Tất nhiên điều này sẽ không hoạt động cho tất cả các trường hợp nhưng bạn có thể thấy rằng nó chỉ cần một chút thiết kế thông minh để làm cho nó rất mạnh mẽ.


16

Trong khi tôi chưa thử nó, một cách tiếp cận điều chỉnh múi giờ tôi sẽ thấy hấp dẫn sẽ như sau:

  1. Lưu trữ mọi thứ trong UTC.

  2. Tạo một bảng TZOffsetscó ba cột: RegionClassId, StartDateTime và OffsetMinutes (int, tính bằng phút).

Trong bảng, lưu trữ danh sách ngày và giờ khi giờ địa phương thay đổi và bao nhiêu. Số lượng vùng trong bảng và số ngày sẽ phụ thuộc vào phạm vi ngày và khu vực trên thế giới bạn cần hỗ trợ. Hãy nghĩ về điều này như thể đó là ngày "lịch sử", mặc dù ngày đó sẽ bao gồm tương lai đến một giới hạn thực tế nào đó.

Khi bạn cần tính thời gian địa phương của bất kỳ thời gian UTC nào, chỉ cần làm điều này:

SELECT DATEADD('m', SUM(OffsetMinutes), @inputdatetime) AS LocalDateTime
FROM   TZOffsets
WHERE  StartDateTime <= @inputdatetime
       AND RegionClassId = @RegionClassId;

Bạn có thể muốn lưu trữ bảng này trong ứng dụng của mình và sử dụng LINQ hoặc một số phương tiện tương tự để thực hiện các truy vấn thay vì nhấn cơ sở dữ liệu.

Dữ liệu này có thể được chưng cất từ cơ sở dữ liệu tz miền công cộng .

Ưu điểm và chú thích của phương pháp này:

  1. Không có quy tắc nào được đưa vào mã, bạn có thể điều chỉnh độ lệch cho các vùng hoặc phạm vi ngày mới một cách dễ dàng.
  2. Bạn không phải hỗ trợ mọi phạm vi ngày hoặc khu vực, bạn có thể thêm chúng khi cần.
  3. Các khu vực không phải tương ứng trực tiếp với các ranh giới địa chính trị và để tránh trùng lặp các hàng (ví dụ: hầu hết các tiểu bang ở Hoa Kỳ xử lý DST theo cùng một cách), bạn có thể có các mục Vùng rộng được liên kết trong một bảng khác với các danh sách truyền thống hơn về tiểu bang, quốc gia, v.v.
  4. Đối với các tình huống như Hoa Kỳ nơi ngày bắt đầu và ngày kết thúc của DST đã thay đổi trong vài năm qua, điều này khá dễ đối phó.
  5. Vì trường StartDateTime cũng có thể lưu trữ thời gian, nên thời gian thay đổi tiêu chuẩn 2:00 AM được xử lý dễ dàng.
  6. Không phải nơi nào trên thế giới cũng sử dụng DST 1 giờ. Điều này xử lý những trường hợp dễ dàng.
  7. Bảng dữ liệu là đa nền tảng và có thể là một dự án nguồn mở riêng biệt có thể được sử dụng bởi các nhà phát triển sử dụng gần như bất kỳ nền tảng cơ sở dữ liệu hoặc ngôn ngữ lập trình nào.
  8. Điều này có thể được sử dụng cho các offset không liên quan đến múi giờ. Chẳng hạn, các điều chỉnh 1 giây xảy ra theo thời gian để điều chỉnh cho vòng quay của Trái đất, các điều chỉnh lịch sử đến và trong lịch Gregorian, v.v.
  9. Vì đây là trong một bảng cơ sở dữ liệu, các truy vấn báo cáo tiêu chuẩn, v.v. có thể tận dụng dữ liệu mà không cần thông qua mã logic nghiệp vụ.
  10. Điều này cũng xử lý các độ lệch múi giờ nếu bạn muốn và thậm chí có thể tính đến các trường hợp lịch sử đặc biệt trong đó một vùng được gán cho múi giờ khác. Tất cả những gì bạn cần là một ngày ban đầu chỉ định độ lệch múi giờ cho từng vùng với ngày bắt đầu tối thiểu. Điều này sẽ yêu cầu tạo ít nhất một vùng cho mỗi múi giờ, nhưng sẽ cho phép bạn hỏi những câu hỏi thú vị như: "Sự khác biệt về giờ địa phương giữa Yuma, Arizona và Seattle, Washington vào ngày 2 tháng 2 năm 1989 lúc 5:00 sáng?" (Chỉ cần trừ một SUM () từ cái kia).

Bây giờ, nhược điểm duy nhất của phương pháp này hoặc bất kỳ cách nào khác là chuyển đổi từ giờ địa phương sang GMT không hoàn hảo, vì bất kỳ thay đổi DST nào có bù trừ âm cho đồng hồ lặp lại theo giờ địa phương nhất định. Không có cách dễ dàng để đối phó với điều đó, tôi sợ, đó là một lý do lưu trữ thời gian địa phương là tin xấu ngay từ đầu.


8
Ý tưởng cơ sở dữ liệu của bạn đã được triển khai như Cơ sở dữ liệu Olson. Mặc dù thời gian tiết kiệm ánh sáng ban ngày tạo ra sự chồng chéo chỉ định múi giờ cụ thể của ánh sáng ban ngày có thể giúp giải quyết vấn đề. 2:15 EST và 2:15 EDT là thời gian khác nhau. Như đã lưu ý trong các bài viết khác chỉ định bù cũng giải quyết sự mơ hồ.
BillThor

5
Vấn đề lớn với việc giữ cơ sở dữ liệu của riêng bạn là giữ cho nó được cập nhật. Olson và Windows được duy trì cho bạn. Tôi đã có nhiều hơn một trường hợp chuyển đổi DST xấu vì các bảng đã hết hạn. Trích xuất chúng hoàn toàn và dựa vào cơ sở dữ liệu mức khung hoặc hệ điều hành là đáng tin cậy hơn nhiều.
Matt Johnson-Pint

4
Không tạo cơ sở dữ liệu của riêng bạn : luôn dựa vào API của hệ thống!
Alex

15

Gần đây tôi đã gặp sự cố trong một ứng dụng web trong đó trên Ajax post-back, datetime quay lại mã phía máy chủ của tôi khác với datetime được cung cấp.

Rất có thể phải thực hiện với mã JavaScript của tôi trên máy khách đã tạo ngày để đăng lại cho máy khách dưới dạng chuỗi, vì JavaScript đang điều chỉnh để tiết kiệm múi giờ và ánh sáng ban ngày và trong một số trình duyệt tính toán khi nào nên áp dụng tiết kiệm ánh sáng ban ngày dường như khác với những người khác

Cuối cùng, tôi đã chọn loại bỏ hoàn toàn các tính toán ngày và thời gian trên máy khách và gửi lại cho máy chủ của mình trên một khóa số nguyên sau đó được dịch sang ngày giờ trên máy chủ, để cho phép biến đổi nhất quán.

Tôi học được từ điều này: Không sử dụng tính toán ngày và thời gian JavaScript trong các ứng dụng web trừ khi bạn TUYỆT ĐỐI.


Javascript chạy ở máy khách, không phải ở máy chủ. Thời gian cơ sở của Javascript là thời gian của máy khách, không phải là thời gian của máy chủ.
BalusC

Xin chào BalusC. Tôi hiểu điều này (từ bài đăng gốc của tôi: "tập lệnh javacode trên máy khách đã tạo ngày ..."). Vấn đề của tôi là máy khách nhất định đã xử lý DST theo một cách và một số cách khác. Do đó, tôi đã di chuyển tất cả phía máy chủ xử lý đó để ngăn chặn sự kỳ lạ của trình duyệt
Joon

@ Joon, và có lỗi trong việc triển khai javascript mà bạn không thể phát hiện hoặc cho phép. Vì vậy, có, đừng bao giờ sử dụng tính toán ngày ECMAScript của khách hàng cho những việc quan trọng (mặc dù bạn có thể làm một công việc khá tốt khác).
RobG

14

Tôi đã đánh vào điều này trên hai loại hệ thống, hệ thống lập kế hoạch thay đổi (ví dụ công nhân nhà máy) hệ thống quản lý phụ thuộc khí đốt và

23 và 25 giờ ngày dài là một nỗi đau để đối phó, vì vậy các ca làm việc 8 giờ mất 7 giờ hoặc 9 giờ. Vấn đề là bạn sẽ thấy rằng mỗi khách hàng, hoặc thậm chí bộ phận của khách hàng có các quy tắc khác nhau mà họ đã tạo (thường không có tài liệu) về những gì họ làm trong những trường hợp đặc biệt này.

Một số câu hỏi tốt nhất là không được hỏi về khách hàng cho đến khi họ trả tiền cho phần mềm của bạn trên phần mềm kệ. Rất hiếm khi tìm thấy một khách hàng nghĩ về loại vấn đề này trước khi mua phần mềm.

Tôi nghĩ trong mọi trường hợp, bạn nên ghi lại thời gian trong UTC và chuyển đổi sang / từ giờ địa phương trước khi lưu trữ ngày / giờ. Tuy nhiên, ngay cả việc biết mất một thời gian nhất định có thể khó khăn với tiết kiệm ánh sáng và múi giờ.


6
Bạn gái của tôi, một y tá, làm việc đêm và họ phải viết múi giờ trong quá trình chuyển đổi DST. Chẳng hạn, 2AM CST so với 2AM CDT
Joe Phillips

1
Vâng, điều này là phổ biến: khi bạn tính trung bình hàng ngày (dân sự), bạn phải đối phó với các ngày 23, 24 hoặc 25 giờ. Kết quả là, khi bạn tính thêm 1 ngày thì không thêm 24 giờ ! Thứ hai, đừng cố gắng xây dựng mã múi giờ của riêng bạn; chỉ sử dụng API hệ thống. Và đừng quên cập nhật từng hệ thống được triển khai để có được cơ sở dữ liệu múi giờ cập nhật .
Alex

12

Đối với web, các quy tắc không phức tạp ...

  • Phía máy chủ, sử dụng UTC
  • Phía khách hàng, sử dụng Olson
    • Lý do: Các khoản giảm giá của UTC không an toàn vào ban ngày (ví dụ: New York là EST (UTC - 5 giờ) trong năm, EDT (UTC - 4 giờ) trong năm).
    • Để xác định múi giờ phía khách hàng, bạn có hai tùy chọn:

Phần còn lại chỉ là chuyển đổi UTC / cục bộ bằng thư viện datetime phía máy chủ của bạn. Tốt để đi...


2
Đây là lời khuyên tốt như một điểm khởi đầu, nhưng nó hoàn toàn phụ thuộc vào ứng dụng. Điều này có thể tốt cho một trang web thân thiện, nhưng nếu có bất kỳ khía cạnh pháp lý / tài phán / tài chính nào đối với ứng dụng của bạn mà ai đó có thể kiện (tôi đã làm việc trên một số), thì đây là một sự đơn giản hóa quá mức vì có nhiều loại khác nhau ' thời gian ', như đã lưu ý ở nơi khác trên trang này.
DavidWalley

12

Khi nói đến các ứng dụng chạy trên máy chủ , bao gồm các trang web và các dịch vụ phụ trợ khác, cài đặt múi giờ của máy chủ sẽ bị ứng dụng bỏ qua.

Lời khuyên phổ biến là đặt múi giờ của máy chủ thành UTC. Đây thực sự là một cách thực hành tốt nhất, nhưng nó có vai trò hỗ trợ ban nhạc cho các ứng dụng không tuân theo các thực tiễn tốt nhất khác. Ví dụ: một dịch vụ có thể ghi vào các tệp nhật ký với dấu thời gian cục bộ thay vì dấu thời gian dựa trên UTC, do đó tạo ra sự mơ hồ trong quá trình chuyển đổi ngược thời gian tiết kiệm ánh sáng ban ngày. Đặt múi giờ của máy chủ thành UTC sẽ khắc phục ứng dụng đó . Tuy nhiên, cách khắc phục thực sự sẽ là ứng dụng đăng nhập bằng UTC để bắt đầu.

Mã phía máy chủ, bao gồm các trang web, không bao giờ mong đợi múi giờ địa phương của máy chủ là bất cứ thứ gì cụ thể.

Trong một số ngôn ngữ, múi giờ địa phương có thể dễ dàng leo vào mã ứng dụng. Ví dụ: DateTime.ToUniversalTimephương thức trong .NET sẽ chuyển đổi từ múi giờ địa phương sang UTC và thuộc DateTime.Nowtính trả về thời gian hiện tại theo múi giờ địa phương. Ngoài ra, hàm Datetạo trong JavaScript sử dụng múi giờ cục bộ của máy tính. Có nhiều ví dụ khác như thế này. Điều quan trọng là phải thực hành lập trình phòng thủ, tránh bất kỳ mã nào sử dụng cài đặt múi giờ địa phương của máy tính.

Dự trữ bằng múi giờ cục bộ cho mã phía máy khách, chẳng hạn như ứng dụng máy tính để bàn, ứng dụng di động và JavaScript phía máy khách.


11

Giữ máy chủ của bạn được đặt thành UTC và đảm bảo tất cả chúng đều được cấu hình cho ntp hoặc tương đương.

UTC tránh các vấn đề về thời gian tiết kiệm ánh sáng ban ngày và các máy chủ không đồng bộ có thể gây ra kết quả không thể đoán trước mà phải mất một thời gian để chẩn đoán.


9

Hãy cẩn thận khi xử lý dấu thời gian được lưu trữ trong hệ thống tệp FAT32 - nó luôn được duy trì trong tọa độ thời gian cục bộ (bao gồm DST - xem bài viết msDN ). Đã bị đốt cháy trên đó.


Điểm tuyệt vời. NTFS không có vấn đề này, nhưng một số người vẫn sử dụng FAT32 - đặc biệt là trên các phím USB.
Matt Johnson-Pint

7

Một điều khác, đảm bảo rằng các máy chủ có bản vá tiết kiệm ánh sáng ban ngày được áp dụng.

Chúng tôi đã có một tình huống vào năm ngoái khi thời gian của chúng tôi liên tục hết một giờ trong khoảng thời gian ba tuần cho người dùng Bắc Mỹ, mặc dù chúng tôi đang sử dụng hệ thống dựa trên UTC.

Hóa ra cuối cùng thì đó là máy chủ. Họ chỉ cần một bản vá cập nhật được áp dụng ( Windows Server 2003 ).


6

DateTimeZone::listAbbreviations()Đầu ra của PHP

Phương thức PHP này trả về một mảng kết hợp có chứa một số múi giờ 'chính' (như CEST), mà chính chúng chứa các múi giờ 'địa lý' cụ thể hơn (như Châu Âu / Amsterdam).

Nếu bạn đang sử dụng các múi giờ này và thông tin bù / DST của chúng, điều cực kỳ quan trọng là phải nhận ra những điều sau:

Có vẻ như tất cả các cấu hình offset / DST khác nhau (bao gồm cả cấu hình lịch sử) của mỗi múi giờ đều được bao gồm!

Ví dụ, Châu Âu / Amsterdam có thể được tìm thấy sáu lần trong đầu ra của chức năng này. Hai lần xuất hiện (bù 1172/4772) là cho thời gian Amsterdam được sử dụng cho đến năm 1937; hai (1200/4800) là thời gian được sử dụng từ năm 1937 đến 1940; và hai (3600/4800) là cho thời gian được sử dụng kể từ năm 1940.

Do đó, bạn không thể dựa vào thông tin offset / DST mà hàm này trả về là hiện đang chính xác / đang sử dụng!

Nếu bạn muốn biết bù / DST hiện tại của một múi giờ nhất định, bạn sẽ phải làm một cái gì đó như thế này:

<?php
$now = new DateTime(null, new DateTimeZone('Europe/Amsterdam'));
echo $now->getOffset();
?>

5

Nếu bạn tình cờ duy trì các hệ thống cơ sở dữ liệu đang chạy với DST hoạt động, hãy kiểm tra cẩn thận xem chúng có cần phải tắt trong quá trình chuyển đổi vào mùa thu hay không. Mandy DBS (hoặc các hệ thống khác cũng vậy) không thích vượt qua cùng một điểm trong thời gian (cục bộ) hai lần, đó chính xác là điều xảy ra khi bạn quay ngược đồng hồ vào mùa thu. SAP đã giải quyết vấn đề này bằng cách giải quyết (IMHO thực sự gọn gàng) - thay vì quay ngược đồng hồ, họ chỉ để đồng hồ bên trong chạy với tốc độ bằng một nửa tốc độ thông thường trong hai giờ ...


4

Bạn đang sử dụng .NET framework ? Nếu vậy, hãy để tôi giới thiệu cho bạn loại DateTimePackset , được thêm bằng .NET 3.5.

Cấu trúc này chứa cả a DateTimevà Offset ( TimeSpan), chỉ định sự khác biệt giữa DateTimeOffsetngày và giờ của trường hợp và Giờ quốc tế phối hợp (UTC).

  • Các DateTimeOffset.Nowphương pháp tĩnh sẽ trả về một DateTimeOffset ví dụ bao gồm các hiện tại (địa phương) thời gian, và các địa phương bù đắp (theo quy định tại thông tin khu vực của hệ điều hành).

  • Các DateTimeOffset.UtcNowphương pháp tĩnh sẽ trả về một DateTimeOffsetví dụ bao gồm thời gian hiện tại UTC (như thể bạn đang ở Greenwich).

Các loại hữu ích khác là các lớp TimeZoneTimeZoneInfo .


Đây không phải là một giải pháp cho vấn đề được trình bày.
caradrye

4

Đối với những người đang vật lộn với điều này trên .NET , hãy xem liệu sử dụng DateTimeOffsetvà / hoặc TimeZoneInfocó đáng để bạn sử dụng không .

Nếu bạn muốn sử dụng múi giờ IANA / Olson hoặc tìm các loại tích hợp không đủ cho nhu cầu của mình, hãy xem Noda Time , nơi cung cấp API ngày và giờ thông minh hơn cho .NET.


4

Các quy tắc kinh doanh phải luôn luôn hoạt động vào thời gian dân sự (trừ khi có luật quy định khác). Xin lưu ý rằng thời gian dân sự là một mớ hỗn độn, nhưng đó là những gì mọi người sử dụng vì vậy đó là điều quan trọng.

Trong nội bộ, giữ dấu thời gian trong một cái gì đó như thời gian dân sự-giây-từ-kỷ nguyên. Các kỷ nguyên không quan trọng đặc biệt (tôi ủng hộ các kỷ nguyên Unix ) nhưng nó làm cho mọi việc dễ dàng hơn thay thế. Giả sử rằng giây nhuận không tồn tại trừ khi bạn đang làm gì đó thực sự cần chúng (ví dụ: theo dõi vệ tinh). Ánh xạ giữa dấu thời gian và thời gian hiển thị là điểm duy nhất áp dụng quy tắc DST ; các quy tắc thay đổi thường xuyên (ở cấp độ toàn cầu, nhiều lần trong năm; đổ lỗi cho các chính trị gia) vì vậy bạn nên đảm bảo rằng bạn không mã hóa bản đồ. Cơ sở dữ liệu TZ của Olson là vô giá.


3
Vấn đề ở đây là thời gian dân sự (còn gọi là thời gian theo lịch) không thể hiện đúng một thời điểm duy nhất. Nếu bạn thực hiện phương pháp tiếp cận từng giây, bạn có thực sự tính đến từng khoảnh khắc bị bỏ qua hoặc quay lại để chuyển đổi tiết kiệm ánh sáng ban ngày không? Chắc là không. Cơ sở Epoch chỉ hoạt động chống lại UTC hoặc một số tham chiếu thời gian tức thời cố định khác.
Matt Johnson-Pint

@MattJohnson Do đó phần "quy tắc kinh doanh". Nếu các quy tắc nói điều gì đó xảy ra vào lúc 2:30 sáng (hoặc bất cứ lúc nào), nó sẽ xảy ra hai lần vào một ngày một năm và không bao giờ vào một ngày một năm. Đó là những gì khách hàng mong đợi sẽ xảy ra nếu họ không làm rõ quy tắc.
dùng253751

Giữ dấu thời gian nội bộ trong thời gian dân sự có thể rất khó khăn. Giữ nó trong vài giây kể từ khi một kỷ nguyên vẫn còn khó khăn hơn, tôi sẽ nói hết sức nguy hiểm. Tôi chắc chắn có những người làm việc đó và có thể khiến nó hoạt động tốt hầu hết thời gian nếu bạn cực kỳ cẩn thận, nhưng nó không thể được coi là một cách thực hành tốt nhất hoặc khuyến nghị chung.
Hội nghị thượng đỉnh Steve

2

Chỉ muốn chỉ ra hai điều có vẻ không chính xác hoặc ít nhất là khó hiểu:

Luôn luôn duy trì thời gian theo một tiêu chuẩn thống nhất không bị ảnh hưởng bởi tiết kiệm ánh sáng ban ngày. GMT và UTC đã được đề cập bởi những người khác nhau, mặc dù UTC dường như được đề cập thường xuyên nhất.

Đối với (hầu hết) tất cả các mục đích tính toán thực tế, trên thực tế, UTC là GMT. Trừ khi bạn thấy dấu thời gian với một phần giây, bạn đang xử lý GMT khiến cho sự khác biệt này trở nên dư thừa.

Bao gồm bù thời gian cục bộ (bao gồm bù DST) khi lưu dấu thời gian.

Dấu thời gian luôn được thể hiện bằng GMT và do đó không có bù.


1
Thời gian bù giờ cục bộ sẽ cho phép bạn tạo lại "thời gian treo tường" ban đầu của sự kiện. Nếu bạn không lưu trữ trường bổ sung này, dữ liệu này sẽ bị mất.
nogridbag

Có, ngoại trừ các giao dịch UTC và GMT là nghịch đảo. Ví dụ: UTC-0700 giống như GMT + 0700. Thực sự, mọi thứ kỹ thuật số nên được sử dụng UTC những ngày này.
Matt Johnson-Pint

1
@Matt: bạn có chắc chắn về việc bù đắp UTC và GMT là nghịch đảo không? Tôi có thể đọc nó ở đâu?
Reto Höhener

Trên thực tế, tôi nghĩ rằng tôi đã không chính xác trước đây. GMT và UTC không tự đảo ngược. Đó là những triển khai cho thấy chúng nghịch đảo, chẳng hạn như cơ sở dữ liệu IANA / Olson / TZDB. Xem ở đây . Một khu vực khác mà bạn thấy bù đắp ngược lại là trong hàm getTimezone Offerset () của javascript.
Matt Johnson-Pint

@MattJohnson: Đó là những vụ hack và cần được bãi bỏ.
Alix Axel

2

Đây là kinh nghiệm của tôi: -

(Không yêu cầu bất kỳ thư viện của bên thứ ba)

  • Về phía máy chủ, lưu trữ thời gian ở định dạng UTC sao cho tất cả các giá trị ngày / giờ trong cơ sở dữ liệu nằm trong một tiêu chuẩn duy nhất bất kể vị trí của người dùng, máy chủ, múi giờ hoặc DST.
  • Trên lớp UI hoặc trong các email được gửi cho người dùng, bạn cần hiển thị thời gian theo người dùng. Đối với vấn đề đó, bạn cần phải có bù múi giờ của người dùng để bạn có thể thêm phần bù này vào giá trị UTC của cơ sở dữ liệu, điều này sẽ dẫn đến giờ địa phương của người dùng. Bạn có thể lấy phần bù múi giờ của người dùng khi họ đăng ký hoặc bạn có thể tự động phát hiện chúng trong các nền tảng web và di động. Đối với các trang web, phương thức hàm getTimezone Offerset () của JavaScript là một tiêu chuẩn kể từ phiên bản 1.0 và tương thích với tất cả các trình duyệt. (Tham khảo: http://www.w3schools.com/jsref/jsref_getTimezone Offerset.asp )

Điều này không hoạt động khi bạn xem xét thay đổi DST. getTimezoneOffsettrả về giá trị bù cho ngày và thời gian bạn gọi nó vào. Phần bù đó có thể thay đổi khi múi giờ chuyển đổi trong hoặc ngoài thời gian tiết kiệm ánh sáng ban ngày. Xem "múi giờ! = Offset" trong wiki thẻ múi giờ .
Matt Johnson-Pint

1
Nếu bạn muốn lưu trữ một báo thức như "làm gì đó lúc 10:00", bạn không thể lưu nó trong UTC, vì các ca DST. Bạn phải lưu trữ nó liên quan đến giờ địa phương.
Alex

2

Video của Tom Scott về các múi giờ trên YouTube trên kênh Computerphile cũng là một mô tả hay và thú vị về chủ đề này. Những ví dụ bao gồm:

  • Samoa (một hòn đảo ở Thái Bình Dương) thay đổi múi giờ của mình trước 24 giờ để giao dịch dễ dàng hơn với Úc và New Zealand,
  • Bờ Tây , nơi có 2 nhóm người theo các múi giờ khác nhau,
  • Thế kỷ 18 thay đổi từ lịch Julian sang lịch Gregorian (xảy ra vào thế kỷ 20 ở Nga).

1

Trên thực tế, kernel32.dll không xuất SystemTimeToTzSpecificLocation. Tuy nhiên, nó xuất hai cái sau: SystemTimeToTzSpecificLocalTime và TzSpecificLocalTimeToSystemTime ...


1

Không bao giờ chỉ dựa vào các nhà xây dựng như

 new DateTime(int year, int month, int day, int hour, int minute, TimeZone timezone)

Họ có thể ném ngoại lệ khi thời gian ngày nhất định không tồn tại do DST. Thay vào đó, xây dựng các phương pháp của riêng bạn để tạo ra những ngày như vậy. Trong đó, bắt bất kỳ trường hợp ngoại lệ nào xảy ra do DST và điều chỉnh thời gian là cần thiết với phần bù chuyển tiếp. DST có thể xảy ra vào các ngày khác nhau và vào các giờ khác nhau (thậm chí vào nửa đêm đối với Brazil) theo múi giờ.


1

Chỉ cần một ví dụ để chứng minh rằng thời gian xử lý là mớ hỗn độn khổng lồ được mô tả và bạn không bao giờ có thể tự mãn. Trong một số điểm trên trang này, bước nhảy vọt đã bị bỏ qua.

Cách đây vài năm, hệ điều hành Android đã sử dụng các vệ tinh GPS để có được tham chiếu thời gian UTC, nhưng bỏ qua thực tế là các vệ tinh GPS không sử dụng bước nhảy vọt. Không ai nhận thấy cho đến khi có sự nhầm lẫn vào đêm giao thừa, khi người dùng điện thoại Apple và người dùng điện thoại Android đã đếm ngược cách nhau khoảng 15 giây.

Tôi nghĩ rằng nó đã được sửa chữa, nhưng bạn không bao giờ biết khi nào những 'chi tiết nhỏ' này sẽ quay trở lại ám ảnh bạn.


1
  • Không bao giờ, không bao giờ lưu trữ giờ địa phương mà không có bù UTC (hoặc tham chiếu đến múi giờ) các biểu thức về cách không thực hiện bao gồm FAT32 và struct tmtrong C.¹
  • Hiểu rằng múi giờ là sự kết hợp của
    • một bộ bù đắp UTC (ví dụ +0100 vào mùa đông, +0200 vào mùa hè)
    • các quy tắc khi chuyển đổi xảy ra (có thể thay đổi theo thời gian: ví dụ, trong những năm 1990, EU đã hài hòa việc chuyển đổi như vào Chủ nhật cuối tháng 3 và tháng 10, lúc 02:00 giờ chuẩn / 03: 00 DST; trước đây điều này khác giữa các quốc gia thành viên).

Một số triển khai thực hiện struct tmlưu trữ bù UTC, nhưng điều này chưa làm cho nó trở thành tiêu chuẩn.


-4

Khi xử lý các cơ sở dữ liệu (cụ thể là MySQL , nhưng điều này áp dụng cho hầu hết các cơ sở dữ liệu), tôi thấy khó lưu trữ UTC.

  • Cơ sở dữ liệu thường hoạt động với datetime của máy chủ theo mặc định (nghĩa là CURRENT_TIMESTAMP).
  • Bạn không thể thay đổi múi giờ của máy chủ.
  • Ngay cả khi bạn có thể thay đổi múi giờ, bạn có thể có mã của bên thứ ba hy vọng múi giờ của máy chủ là cục bộ.

Tôi thấy việc lưu trữ datetime máy chủ trong cơ sở dữ liệu trở nên dễ dàng hơn, sau đó cho phép cơ sở dữ liệu chuyển đổi datetime được lưu trữ trở lại thành UTC (nghĩa là UNIX_TIMESTAMP ()) trong các câu lệnh SQL. Sau đó, bạn có thể sử dụng datetime như UTC trong mã của mình.

Nếu bạn có quyền kiểm soát 100% đối với máy chủ và tất cả mã, có lẽ tốt hơn là thay đổi múi giờ của máy chủ thành UTC.


Giờ địa phương (giờ máy chủ) có thể không rõ ràng trong quá trình chuyển đổi tiết kiệm ánh sáng ban ngày kiểu "dự phòng". Nó không đáng tin cậy để sử dụng như bạn mô tả. Có thể có nhiều hơn một thời gian UTC mà giờ địa phương của máy chủ có thể đại diện.
Matt Johnson-Pint

Giờ địa phương là hoàn toàn tốt nếu máy chủ được đặt trong múi giờ lành mạnh, tức là máy chủ không thực hiện DST.
sayap
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.