Thời gian Unix và lối viết ISO 8601
Đơn vị ngoài SI · đại lượng: một thời điểm dưới dạng số nguyên giây kể từ 1970
Ngày 19 tháng Giêng năm 2038, vào lúc ba giờ mười bốn phút bảy giây theo giờ thế giới, một bộ đếm giây rộng ba mươi hai bit sẽ tới 2 147 483 647 — con số lớn nhất mà nó chứa nổi. Nhịp kế đó sẽ nâng bit cao nhất lên, và cũng chính từ nhị phân ấy từ nay sẽ được đọc là số âm: những đồng hồ giữ thời gian đúng bằng phép đếm này sẽ thấy mình không ở năm 2038, mà ở tháng Chạp năm 1901. Đây chẳng phải chuyện lạ của tương lai xa — một bộ điều khiển công nghiệp hay một đồng hồ nước còn phục vụ lâu hơn mười hai năm còn lại.
Phép đếm được dựng lên hết sức giản dị: các giây nối nhau chạy từ nửa đêm ngày 1 tháng Giêng năm 1970, và một ngày trong đó luôn chứa đúng 86 400 giây. Chính sự giản dị ấy là ngọn nguồn của cả hai đặc tính. Một mặt, từ con số lập tức suy ra ngày tháng theo lịch và ngược lại, khiến mọi nhật ký sự kiện, mọi cơ sở dữ liệu và mọi hệ thống tệp đều giữ thời gian bằng nó. Mặt khác, giây nhuận hoàn toàn không thể diễn tả trong một phép đếm như thế, nghĩa là trái với tên gọi, nó đánh số không phải giây mà là ngày kèm phần lẻ, và thực chất là một hàm bậc nhất của lối viết UTC chứ không phải bộ đếm thời gian đã trôi qua.
01 · Định nghĩa
Thời gian Unix là số giây đã trôi qua kể từ nửa đêm ngày 1 tháng Giêng năm 1970 theo giờ phối hợp quốc tế, với điều kiện mỗi ngày chứa đúng 86 400 giây. Lối viết ISO 8601 nói cũng điều ấy theo cách khác: bằng ngày tháng theo lịch, giờ trong ngày và việc chỉ ra độ lệch so với kinh tuyến gốc, các trường chạy nghiêm ngặt từ thô đến tinh.
Điều dè dặt về 86 400 giây chẳng phải chuyện vặt, mà là cốt lõi nhất trong định nghĩa. Giây nhuận, do cơ quan lo việc quay của Trái Đất công bố, phép đếm không sao dung nạp nổi, nên vào khoảnh khắc chèn thêm, hệ thống hoặc lặp lại một và cùng một giá trị hai lần, hoặc vặn đồng hồ lùi lại. Từ đó rút ra điều quan trọng: hiệu của hai con số unix không phải là số giây đã thực sự trôi qua giữa hai sự kiện, nếu giữa chúng có một lần chèn — độ lệch so với thang nguyên tử đã dồn tới hai mươi bảy giây.
Còn giới hạn thì không tùy thuộc định nghĩa, mà tùy bề rộng của chỗ lưu. Ba mươi hai bit có dấu cho giá trị lớn nhất là 2 147 483 647, rơi vào ngày 19 tháng Giêng năm 2038; lần tăng kế tiếp đưa bit cao nhất về một và khiến con số thành âm, ném đồng hồ về ngày 13 tháng Chạp năm 1901. Sáu mươi tư bit đẩy ranh giới tới trước hai trăm chín mươi hai tỉ năm, song nano giây nguyên trong chính sáu mươi tư bit ấy lại cạn ngay từ năm 2262.
Lối viết theo tiêu chuẩn giải một việc khác — trao đổi chứ không phải lưu giữ — nên trong đó lại nặng những thứ mà con số hoàn toàn không có: độ lệch giờ, dấu phân cách giữa ngày và giờ, cùng quy tắc rằng khi các chuỗi dài bằng nhau thì thứ tự từ điển trùng với thứ tự thời gian. Chính tính chất sau cùng ấy đã khiến định dạng này thành nền tảng của việc sắp xếp trong tên tệp và trong nhật ký.
Xin dẫn thời gian bằng con trượt và xem thanh ghi đầy dần: các bit sáng lên từ phải sang trái, và chừng nào bit cao nhất, bit dấu, còn tối thì con số vẫn dương và ngày tháng vẫn lớn lên. Vừa lúc bộ đếm bước qua 2 147 483 647, bit cao nhất bùng đỏ, cả con số hóa âm, và đồng hồ nhảy về năm 1901.
Đường thẳng màu lục là thang nguyên tử, nơi mỗi giây quả thực là một giây. Đường bậc thang màu đỏ là thời gian Unix, cứ mỗi lần chèn lại phát ra cùng một dấu hai lần, khiến đường đứng lại tại chỗ. Độ lệch nay đã là hai mươi bảy giây và còn lớn lên, nên phép đếm dùng cho ngày tháng theo lịch thì được, còn dùng để đo khoảng kéo dài trong vật lý thì không.
02 · Quy đổi
Xin nhập dấu thời gian hoặc ngày tháng
Giữa mọi bội của phép đếm — giây, mili giây, micro và nano giây — các phép quy đổi đều chính xác, vì chúng chỉ khác nhau một thừa số. Chỉ một dòng là gần đúng: quy đổi sang thang nguyên tử đòi phải biết cho tới thời điểm đã cho đã dồn được bao nhiêu giây nhuận.
Việc phân tích một chuỗi theo tiêu chuẩn, trang này làm ở lối viết mở rộng có chữ Z; dạng cơ bản không dấu phân cách được đưa vào phần cài đặt tinh.
Vấn đề năm 2038 không nằm ở tiêu chuẩn, mà ở phần cứng và ở mã cũ: những dấu thời gian ba mươi hai bit ngồi trong phần mềm nhúng của các đồng hồ đo, trong bộ điều khiển công nghiệp, trong định dạng của các hệ thống tệp, và trong những cơ sở dữ liệu mà trường đã được khai là bốn byte. Đổi kiểu trong mã nguồn thì đủ dễ; còn rà hết hàng triệu thiết bị đã lắp đặt trong mười hai năm còn lại là công việc cùng loại với việc từng đứng trước năm 2000.
| Giá trị | Ghi chú | ||
|---|---|---|---|
| {u} | {name} | {value} | {note} |
03 · Bậc độ lớn
thang lôgarit: từ một giây tới giới hạn của sáu mươi tư bit04 · Dụng cụ đo
Người ta đóng dấu thời gian lên sự kiện bằng gì
Một con chip riêng có pin, vẫn giữ phép đếm trong lúc thiết bị đã tắt. Nó thường lưu không phải dấu unix, mà lưu riêng từng trường của lịch, và bề rộng trường năm của nó là của riêng nó, nên ở các bo mạch cũ, câu chuyện về năm 2038 thường bắt đầu từ câu hỏi: chính con chip đếm được tới năm nào.
Giao thức NTP đưa đồng hồ của máy về thời gian chung với độ chính xác vài mili giây, và cũng chính nó báo trước một lần chèn bằng cờ riêng trước một ngày. Nó cũng có ranh giới của mình, và ranh giới ấy tới sớm hơn: phép đếm chạy từ năm 1900 trong ba mươi hai bit không dấu và sẽ tràn vào tháng Hai năm 2036.
Vào nhật ký, dấu thời gian được viết hoặc bằng số, hoặc bằng chuỗi theo tiêu chuẩn, và cách sau đáng chuộng hơn đúng vì một lẽ: ở những chuỗi dài bằng nhau, thứ tự chữ cái trùng với thứ tự thời gian, nên các mục sắp được mà chẳng phải phân tích ngày tháng. Chính vì thế định dạng này đã lan xa ra ngoài kỹ thuật tính toán.
Mức sẵn sàng của một thiết bị cho năm 2038 chỉ có thể thử theo một cách duy nhất — vặn đồng hồ của nó vượt qua ranh giới định mệnh ấy rồi xem nhật ký, chứng thư và phép tính khoảng sẽ ra sao. Bằng cách ấy người ta đã tìm thấy hỏng hóc trong việc tính cước, trong hệ thống kiểm soát ra vào và trong hạn dùng của khóa, nơi ngày tháng tương lai được dựng nên bằng phép cộng và tràn từ rất lâu trước chính ranh giới.
05 · Quy tắc viết
Từ thô đến tinh, và luôn kèm độ lệch
Tiêu chuẩn đòi các trường xếp theo thứ tự giảm dần, năm gồm bốn chữ số, dấu nối làm dấu phân cách ngày tháng và chữ T đặt trước giờ; độ lệch giờ được chỉ ra hoặc bằng chữ Z cho kinh tuyến gốc, hoặc dưới dạng cộng trừ giờ và phút. Dấu unix viết bằng số nguyên, không tách hàng, và bội luôn phải nói rõ, bởi thừa số một nghìn tách giây khỏi mili giây, mà cứ nhìn độ lớn con số thì hai thứ ấy rất dễ lẫn.
Lối viết thứ nhất mỗi nước đọc một khác, nên không dùng được trong trao đổi dữ liệu. Lối thứ hai bỏ cả dấu phân cách lẫn độ lệch, khiến thời điểm còn bỏ ngỏ một ngày về mỗi phía. Lối thứ ba đánh mất các số không ở đầu, do đó chuỗi thôi không sắp theo chữ cái nữa — mà định dạng được trọng chính vì tính chất đó. Lối thứ tư đặt dấu bằng giữa phép đếm unix và thang nguyên tử, trong khi giữa chúng nằm hai mươi bảy giây chèn đã dồn lại.
06 · Các đơn vị lân cận
Kề bên là mọi phép đếm dựng theo cùng một nguyên tắc, chỉ khác khởi điểm: thời gian NTP từ năm 1900, ngày Julius từ giữa trưa năm 4713 trước công nguyên, thang của hệ vệ tinh từ tháng Giêng năm 1980. Chúng chỉ khác nhau ở kỷ nguyên và đơn vị, nên quy đổi bằng cách trừ đi một hằng số.
giây có dấu
giới hạn của nó đã rơi vào 2036
giây nhuận được tính đủ
Trong các phiếu của Simetrium bên cạnh là ngày Julius, nơi hằng số quy đổi được lấy ra, các thang UTC, TAI và UT1, những thang giải thích các giây nhuận đã mất, giây với tư cách đơn vị của phép đếm, và bit, mà chính bề rộng của nó định ra giới hạn.
07 · Phần lịch sử
Một kỷ nguyên chọn ra vì thiếu bit
Trong cuốn cẩm nang Unix đầu tiên, thời gian được đếm bằng một phần sáu mươi của giây kể từ đầu năm 1971, và trong ba mươi hai bit phép đếm như thế chỉ chứa nổi chừng hai năm. Chúng cạn nhanh đến mức phải dời kỷ nguyên mỗi lần ra bản mới, nên người ta bỏ phần lẻ của giây mà lấy giây nguyên.
Chuyển sang giây nguyên, những người làm ra nó có được phần dự trữ một trăm ba mươi sáu năm và chọn được khởi điểm theo tiện lợi chứ không phải theo túng thế. Người ta lấy ngày 1 tháng Giêng năm 1970 — ngày chẵn gần nhất trong quá khứ, mà ghi chép của máy dẫu sao cũng chẳng với tới — và từ đó chưa một lần thay đổi, dẫu hệ thống đã hơn một lần được viết lại từ gốc.
Tổ chức Tiêu chuẩn hóa Quốc tế đã gom các định dạng quốc gia đang phân ly về làm một và đặt vào nền của nó một quy tắc giản dị: các trường chạy từ thô đến tinh, thảy đều có số không ở đầu. Hệ quả phụ hóa ra còn quan trọng hơn chủ ý — những chuỗi như thế sắp được như số, nên định dạng lan vào tên tệp, nhật ký và các giao thức trao đổi.
Hệ thống để bàn và hệ thống máy chủ đã chuyển sang sáu mươi tư bit từ lâu, và ở đó ranh giới đã bị đẩy ra ngoài mọi chân trời hợp lẽ. Mối nguy còn lại ở chỗ khác: ở phần mềm nhúng của những thiết bị có tuổi thọ hai mươi năm, ở các định dạng tệp mà trường được khai là bốn byte, và ở phép tính các kỳ hạn tương lai, vốn đã tràn ngay hôm nay chỉ cần cộng mười lăm năm vào ngày hiện tại.
Một phép đếm, trái với tên gọi, lại không đếm giây
Định nghĩa thời gian Unix nghe như một phép đếm giây, song đòi hỏi mỗi ngày phải chẵn 86 400 giây lại biến nó thành thứ khác: một hàm bậc nhất của lối viết UTC chứ không phải thước đo thời gian đã trôi. Mỗi lần cơ quan lo việc quay của Trái Đất công bố một lần chèn, phép đếm buộc phải lặp cùng một giá trị hai lần hoặc nhảy lùi, và hiệu của hai dấu thời gian mất đi đúng cái giây ấy. Trong nửa thế kỷ đã dồn được hai mươi bảy lần mất như vậy, nên với những việc cần khoảng kéo dài thật, người ta lấy thang nguyên tử chứ không lấy thang này.
Đặc tính thứ hai hoàn toàn không nằm ở định nghĩa, mà ở cách lưu giữ, và chính điều đó khiến nó thành giới hạn duy nhất trong danh mục của ta mà chẳng phải tự nhiên hay thỏa thuận đặt ra, mà là bề rộng của một từ máy. Ngày Julius không bao giờ hết, vì nó là một con số; thời gian Unix hết vào ngày 19 tháng Giêng năm 2038, vì nó là một trường bốn byte. Sự khác biệt giữa một đại lượng và cách biểu diễn nó thường ít bận lòng các nhà đo lường, còn ở đây chính nó quyết định tất cả.
Danh mục · đơn vị đo
Mỗi đại lượng một phiếu
Bảy đơn vị cơ bản của SI, hai mươi hai đơn vị dẫn xuất có tên riêng và các đại lượng ngoài hệ, thiếu chúng thì kỹ thuật lẫn lịch đều không chạy.