Thời gian đã trôi qua kể từ epoch
(aphyr.com)- POSIX time/Unix time thường được gọi là số giây kể từ 1970-01-01 00:00:00, nhưng trên thực tế đó là giá trị dựa trên UTC nhưng bỏ qua giây nhuận, nên lệch với số giây thực sự đã trôi qua
- Tính đến 2024-12-25 18:51:26 UTC, POSIX time là 1735152686, còn số giây thực sự đã trôi qua kể từ epoch là 1735152713 giây, chênh lệch 27 giây
- Khi định nghĩa
seconds since the Epoch, IEEE 1003.1 luôn tính một ngày là 86.400 giây, và phụ lục của chuẩn cũng bỏ qua 14 giây nhuận được thêm từ năm 1970 để thuận tiện cho tính toán và khả năng tương thích - UTC thêm giây nhuận để giảm sai khác với ngày Mặt Trời; khi đó POSIX time có thể nhảy lùi, dẫn đến các sự cố như trên Linux, Qantas và Cloudflare DNS
- Để đo khoảng thời gian trên một máy,
CLOCK_MONOTONIChoặcCLOCK_BOOTTIMEphù hợp hơn; nếu cần khớp với POSIX timestamp thì nên cân nhắc leap smear hoặc chuyển đổi POSIX↔TAI
POSIX time không phải là số giây thực sự đã trôi qua
- JavaScript
Date, GNU coreutils, Linuxtime(2), Gotime.Unix, MySQLdatetime, RubyTime, Cassandratimestampv.v. thường xử lý POSIX time như thể đó là số giây kể từ Unix epoch - Nhưng cách diễn đạt này không hoàn toàn khớp với trực giác thông thường
- Mốc thời gian ví dụ: 2024-12-25 18:51:26 UTC
- POSIX time: 1735152686
- Số giây thực sự đã trôi qua kể từ POSIX epoch: 1735152713
- Chênh lệch: 27 giây
- Sự khác biệt này xuất hiện vì POSIX time được suy ra từ IEEE 1003.1 và UTC, nhưng lại giả định mọi ngày đều có đúng 86.400 giây
- Định nghĩa
seconds since the Epochtrong chuẩn tính giá trị bằngtm_sec,tm_min,tm_hour,tm_yday,tm_year, và không định nghĩa quan hệ với các giá trị nhỏ hơn năm 1970 hoặc giá trị âm - Độ dài thực tế của một ngày không phải lúc nào cũng là 86.400 giây và thay đổi theo thời gian
- Các nhà thiên văn học định kỳ công bố giây nhuận để ngày UTC không lệch quá xa khỏi ngày Mặt Trời
- Kết quả là POSIX time có thể nhảy lùi vài năm một lần
- Và trong tương lai cũng có thể nhảy tiến
- Giây nhuận đã từng gây ra sự cố thực tế
- Vấn đề giây nhuận liên quan đến Linux kernel
- Sự chậm trễ của Qantas do lỗi giây nhuận trên Linux
- Ảnh hưởng của giây nhuận đến Cloudflare DNS
Sự thỏa hiệp của chuẩn và các lựa chọn thay thế trong thực tế
- Phụ lục B của IEEE 1003 tóm tắt rằng tại thời điểm ban hành chuẩn đã có 14 giây nhuận được thêm sau 1970-01-01, nhưng các giây này bị bỏ qua để việc tính toán đơn giản hơn và đảm bảo khả năng tương thích
- Chuẩn giả định giá trị “time” của hầu hết hệ thống tăng liên tục, và chọn hướng giá trị này vẫn phải tăng ngay cả trong lúc có giây nhuận
- Đồng thời cũng giả định rằng phần lớn hệ thống không theo dõi giây nhuận hoặc có thể không được đồng bộ với chuẩn thời gian chuẩn
- Vì vậy, nó không yêu cầu
seconds since the Epochnhất thiết phải biểu diễn chính xác số giây giữa thời điểm tham chiếu và epoch - Chỉ cần ứng dụng có thể xử lý giá trị này như số giây kể từ epoch, còn mức độ chính xác cần thiết là việc của nhà cung cấp hệ thống và quản trị viên
- Trong các ứng dụng phân tán, sự kiện được đồng bộ bằng timestamp nên cách diễn giải nhất quán có thể trở nên quan trọng
- Việc tích lũy giây nhuận là không thể dự đoán trước
- Số giây nhuận kể từ epoch có khả năng còn tiếp tục tăng
- Chuẩn quan tâm nhiều hơn đến việc đồng bộ thời gian giữa các ứng dụng trong các khoảng thời gian ngắn theo góc nhìn thiên văn
- Trên thực tế, hệ thống thường vẫn hoạt động dù thời gian hơi lệch, nhưng vì giây nhuận hiếm gặp và trực giác tuyến tính của “số giây kể từ epoch” rất mạnh, nên có thể tích lũy nhiều lỗi chưa bị phát hiện
- Các lựa chọn thay thế theo từng tình huống gồm có
- Nếu chỉ cần tính duration giữa hai sự kiện trên một máy, dùng
CLOCK_MONOTONIC, hoặc tốt hơn nữa làCLOCK_BOOTTIME - Nếu không cần trao đổi timestamp với các hệ thống khác giả định POSIX time, hãy dùng TAI, GPS, LORAN
- Nếu cần khớp tương đối với các hệ thống POSIX timestamp, dùng leap smear để dàn đều giây nhuận trên một khoảng thời gian dài hơn
- Có thể chuyển đổi giữa POSIX và TAI bằng thư viện như qntm no t-a-i
- Nếu chỉ cần tính duration giữa hai sự kiện trên một máy, dùng
- Các nỗ lực nhằm bãi bỏ giây nhuận đang được tiến hành và được kỳ vọng sẽ thành hiện thực trước năm 2035
- Điều này sẽ đòi hỏi thêm công việc để đưa bảng chuyển đổi vào mọi thứ đang phụ thuộc vào giả định
một ngày có 86.400 giây - Đối với các thời điểm sau năm 2035, những câu hỏi như “có bao nhiêu giây giữa hai thời điểm” có thể trở nên đơn giản hơn rất nhiều
- Điều này sẽ đòi hỏi thêm công việc để đưa bảng chuyển đổi vào mọi thứ đang phụ thuộc vào giả định
1 bình luận
Ý kiến trên Hacker News
Tôi vừa đọc xong tiểu thuyết khoa học viễn tưởng năm 2000 của Vernor Vinge, A Deepness in the Sky; đây là một cuốn sách tuyệt vời với một nhắc đến bất ngờ về số giây kể từ epoch (seconds since the epoch)
Bắt đầu bằng câu “Hãy nhìn cách Traders đo thời gian…”, sách mô tả rằng Qeng Ho đếm theo giây từ khoảnh khắc nhân loại lần đầu đặt chân lên Mặt Trăng của Old Earth, nhưng nếu xem kỹ hơn thì mốc bắt đầu thực ra muộn hơn khoảng 15 triệu giây, tức giây 0 của một trong những hệ điều hành máy tính thời kỳ đầu của loài người
Nếu muốn thêm kiểu “khoa học máy tính trong vũ trụ”, tôi khuyên đọc series Bobiverse; nếu muốn đào sâu hơn về “con người + mô phỏng + máy tính” thì nên đọc Permutation City
Mỗi lần đọc về đo thời gian, tôi đều học được điều gì đó mới. Trước đây tôi nghĩ Unix time là cách đơn giản nhất để theo dõi thời gian nếu chỉ tính đến rollover, và tôi có biết về giây nhuận, nhưng chưa từng nghĩ nó cũng áp dụng ở đây
Tôi cũng đã đọc liên kết “UTC, GPS, LORAN and TAI”, và thấy sự tương phản ở việc giờ GPS không phản ánh giây nhuận khá thú vị
Tôi không thích lắm kế hoạch “đang có nỗ lực loại bỏ giây nhuận trước năm 2035”
Điểm cốt lõi của UTC là lệch khỏi TAI một số nguyên giây và xấp xỉ giờ Mặt Trời trung bình (MST). Nếu không còn theo dõi MST nữa thì nên chuyển hẳn sang TAI
Nếu cứ để UTC trôi xa khỏi MST, ta rơi vào một trạng thái nửa vời: vẫn phải xử lý các giây nhuận trong quá khứ, nhưng chúng không còn mục đích nữa
Tuy vậy đề xuất này không hoàn toàn vô nghĩa. Mục đích là không thay đổi cách quản lý thời gian UTC hiện có, đồng thời khiến chênh lệch giữa hai timestamp sau năm 2035 trở thành đúng số giây vật lý
Dù vậy, vì MST vốn đã là một chức năng của UTC, việc loại bỏ nó trông khá buồn cười
Nhưng trong thực tế, nhiều hệ thống đã chọn sai, đặc biệt UNIX là nguyên nhân lớn nhất. Lựa chọn đó đã ăn sâu vào vô số hệ thống và quy định, nên “cứ chuyển sang TAI” gần như là bất khả thi
Vì vậy, diễn giải lại UTC thành “TAI mới” sẽ dễ hơn. Tôi sẽ không ngạc nhiên nếu một ngày nào đó UTC cũ xuất hiện trở lại dưới một cái tên khác
Ở hầu hết hoặc tất cả các quốc gia, giờ dân dụng dựa trên UTC. Sẽ không có chuyện vặn đồng hồ toàn thế giới lùi khoảng 30 giây chỉ vì nó thuần túy hơn một chút
Giờ GPS cũng có offset với TAI nhưng chẳng ai quá bận tâm. Unix epoch cũng vậy; miễn là kết quả nhất quán thì đủ
Leap_Second. Hằng tháng kiểm tra xem file này có tồn tại không; nếu có thì xóa nó, cộng 1 vào giá trị trong fileLeap_Seconds, rồi tạo một bản sao lưu tênLSSE“You are not expected to understand this.” Đây là cách duy trì cả hai hệ thống. Nếu muốn cũng có thể làm bằng hash hoặc bảng tra cứu
Một điểm quan trọng nữa là UTC epoch hiện đại là ngày 1 tháng 1 năm 1972. Trước đó UTC dùng độ dài giây khác với TAI
Cuối năm 1971, ở giai đoạn chuyển tiếp, có một bước nhảy bất quy tắc cuối cùng chính xác 0,107758 giây TAI; các bước thời gian nhỏ và các điều chỉnh tần số của UTC hoặc TAI trong giai đoạn 1958–1971 được căn sao cho tổng đúng bằng 10 giây. Vì vậy 1972-01-01 00:00:00 UTC chính xác là 1972-01-01 00:00:10 TAI, và từ đó về sau chênh lệch là số nguyên giây
Đồng thời, tốc độ tick của UTC trở nên đúng bằng TAI, và UTC bắt đầu theo dõi UT1 thay vì UT2. Do đó Unix time trong các năm 1970 và 1971 không khớp với thời gian UTC thực tế của giai đoạn đó
https://en.wikipedia.org/wiki/Coordinated_Universal_Time#His...
https://en.wikipedia.org/wiki/Unix_time#UTC_basis
Ngay cả khi giả định thời gian trên giấy khai sinh chính xác đến từng giây cũng vậy. Lý do là trong một phần cuộc đời của họ, giá trị được coi là “độ dài của 1 giây” khá khác so với 1 giây mà ngày nay chúng ta thường nghĩ đến
Ở đây giây có nghĩa là giây dựa trên tần số chuyển tiếp siêu tinh tế của trạng thái cơ bản không bị nhiễu loạn của nguyên tử cesium-133, 9.192.631.770/s
Gần đây tôi viết một đoạn mã cho một sàn giao dịch, hệ thống đó chạy trên VAX, hay chính xác là trên OpenVMS, và epoch của nó là ngày 17 tháng 11 năm 1858
Đây là lần đầu tiên trong sự nghiệp tôi thấy một epoch không phải Unix; may là trong phần mã đang dùng, nó đã được trừu tượng hóa thành Unix epoch
https://www.slac.stanford.edu/~rkj/crazytime.txt
Để nhét các ngày này vào bộ nhớ máy tính thập niên 1950, người ta offset lịch đi 2,4 triệu ngày, kết quả là ngày 0 trở thành 17 tháng 11 năm 1858
https://www.joelonsoftware.com/2006/06/16/my-first-billg-rev...
API macOS/Swift Foundation
NSDate.timeIntervalSinceReferenceDatedùng ngày 1 tháng 1 năm 2001 làm epochWikipedia cũng có một danh sách hữu ích: https://en.wikipedia.org/wiki/Epoch_(computing)#Notable_epoc...
Có những thời điểm không thể biểu diễn bằng timestamp POSIX, và có những timestamp POSIX không tương ứng với thời gian thực
Nói thế giống như nói có những thời điểm không có năm ISO 8601. Mọi thời điểm đều có năm, chỉ là một số năm dài hơn những năm khác mà thôi
Nếu ngồi nhìn https://time.is/UTC, thời gian sẽ tăng đơn điệu, thỉnh thoảng chỉ có một giây dài hơn một chút. Ví dụ như dài hơn khoảng 0,001% trong 24 giờ
Khi lưu ngày vào cơ sở dữ liệu, tôi luôn lưu dưới dạng Unix epoch time, và không ghi thông tin múi giờ trong trường ngày. Nếu có yêu cầu cần biết múi giờ thì lưu riêng
Tôi tự hỏi liệu thay vào đó có nên lưu timestamp ở định dạng TAI, rồi dùng hàm chuyển đổi sang UTC khi cần, để có thể xử lý các hiệu chỉnh liên quan đến Trái Đất khi cần không
Tôi biết múi giờ là một bãi mìn, nhưng bản thân nó cũng là cấu trúc do con người tạo ra, với ranh giới múi giờ thay đổi theo thời gian. Có lẽ nên cố định vào thời gian tuyệt đối rồi khi cần thì render sang định dạng giờ địa phương mong muốn
Việc điều chỉnh giây nhuận nên diễn ra ở cùng chỗ với chuyển đổi múi giờ. Tiếc là Unix đã chuẩn hóa cái sai, và việc migration thì khó
Vì vậy mọi đồng hồ dù sao cũng được căn theo UTC. Bạn sẽ phải chuyển từ UTC sang TAI khi lưu, rồi chuyển ngược lại khi đọc, rất dễ thành một mớ hỗn độn
Thông thường cơ sở dữ liệu hoặc không có khái niệm múi giờ cho timestamp đã lưu (SQL Server), hoặc cung cấp kiểu timestamp “nhận biết múi giờ” nhưng chuyển đầu vào sang UTC và bỏ múi giờ gốc (MySQL, Postgres)
Theo tôi biết, chỉ Oracle mới có thể thực sự round-trip và bảo toàn múi giờ không phải local trong kiểu
with time zoneTrong một số phép tính, chênh lệch 1 giây là vấn đề lớn. Khi chọn thứ không phải định dạng phổ biến nhất, phải cẩn thận và cần có lý do chính đáng để đi lệch chuẩn. Chỉ riêng việc khác biệt thôi cũng có thể tạo ra chi phí lớn
Bài này làm tôi cảm giác như Giáng sinh bị phá hỏng. Chẳng có gì thiêng liêng nữa sao? Giây phải là số giây kể từ epoch chứ
Tôi không hiểu tại sao phải bận tâm chuyện nó lệch một chút so với ngày Mặt Trời. Chẳng phải bộ chuyển đổi từ số giây kể từ epoch sang biểu diễn ngày tháng chịu trách nhiệm hiệu chỉnh là được sao?
Tôi không muốn mọi phần mềm phải hard-code việc đưa giây nhuận vào, xử lý smear, và mỗi khi có giây nhuận mới thì trong vòng một tháng lại đòi hỏi cách cập nhật
Từ trước đến nay ta đã không phải lo hay nghĩ về nó, và sau này cũng không cần. Nó đang được xử lý theo cách đúng
Nên thay giây nhuận bằng tên lửa khổng lồ gắn ở xích đạo. Đừng chỉnh đồng hồ, hãy chỉnh hành tinh
Trong truyền thống Hồi giáo cũng có đoạn về tận thế và Kẻ chống Chúa (Dajjal) kiểu chuyện như vậy thực sự xảy ra. “Ngày đầu tiên của Kẻ chống Chúa sẽ như một năm, ngày thứ hai như một tháng, ngày thứ ba như một tuần”; nhiều người hiểu điều đó theo nghĩa đen, tức là như một sự kiện vũ trụ nơi vòng quay của Trái Đất thực sự chậm lại và cuối cùng đảo chiều, khiến Mặt Trời mọc ở phía tây. Đó là dấu hiệu cuối cùng của ngày tận thế nhân loại
Có vẻ như dù vì giây nhuận mà epoch trở thành một thời điểm xa hơn 29 giây so với điều
date +%sngụ ý thì cũng chẳng có gì đáng bận tâmViệc tất cả mọi người thống nhất về một con số N nào đó biểu thị thời gian hiện tại quan trọng hơn nhiều. Con số -29 giây giả định không ảnh hưởng đến thế giới thực. Chẳng lẽ lại chạy routine ngắm tên lửa vào một mục tiêu của 30 năm trước sao
Tôi ủng hộ việc bãi bỏ giây nhuận, nhưng không nghĩ việc nhấn mạnh sự không nhất quán về thời gian là hữu ích. Dù xét kỹ thì điều đó đúng đi nữa
Điều quan trọng hơn là ảnh hưởng đến tương lai. Việc timestamp trong quá khứ có thể lệch vài giây so với phép tính đơn giản “hiện tại - N giây” phần lớn chỉ là một sự thật thú vị, nhưng việc tại một thời điểm nào đó trong tương lai mọi đồng hồ có thể lại phải dịch chuyển thêm 1 giây thì quan trọng hơn. Có nhiều trường hợp thực tế đòi hỏi khá nhiều công sức để tính đến điều này