Timestamp Unix giải thích - epoch, ISO-8601 và múi giờ
Timestamp Unix mã hóa thời gian thành số nguyên - giây (10 chữ số) hoặc mili giây (13 chữ số) từ 1 tháng 1 năm 1970 UTC. ISO 8601 và RFC 2822 thêm chuỗi đọc được với múi giờ. Hướng dẫn này giải thích cách chuyển đổi giữa ba định dạng, tránh lỗi off-by-1000 và xử lý DST đúng cách.
Epoch Unix: giây từ 1970-01-01 UTC
Timestamp Unix - cũng gọi là "thời gian epoch" - là số giây đã trôi qua từ 00:00:00 UTC ngày 1 tháng 1 năm 1970. Điểm tham chiếu đó tùy ý nhưng phổ quát; mọi hệ thống xuất phát từ Unix (Linux, macOS, Android, iOS) và gần như mọi ngôn ngữ lập trình đều theo dõi thời gian nội bộ như một đếm từ thời điểm này.
Một giá trị hiện tại: 1776495426 dịch ra 2026-04-18 12:17:06 UTC. Không có múi giờ mã hóa trong số - nó luôn là UTC - điều này vừa là điểm mạnh (không có nhầm lẫn khi hai hệ thống so sánh timestamp) vừa là cái bẫy (bất cứ cái gì chuyển số thành chuỗi người đọc được đều phải chọn một múi giờ, và thường chọn múi giờ địa phương).
Giây vs mili giây: nguồn nhầm lẫn đầu tiên
JavaScript, Java và hầu hết thư viện chuẩn ngôn ngữ hiện đại mặc định dùng mili giây từ epoch, không phải giây. Cùng khoảnh khắc đó - 2026-04-18 12:17:06 UTC - là 1776495426 giây (10 chữ số) nhưng 1776495426000 mili giây (13 chữ số). Quy tắc kiểm tra nhanh cho timestamp nhận được:
- 10 chữ số → giây (dòng lệnh Unix, PHP, Python
time.time(), Go). - 13 chữ số → mili giây (JavaScript
Date.now(), JavaSystem.currentTimeMillis(), hầu hết API JSON). - 16 hoặc 19 chữ số → micro giây hoặc nano giây (telemetry chuyên biệt và đo thời gian khoa học).
Giá trị 10 chữ số theo giây được hiểu là mili giây render thành ngày năm 1970 (sớm 50+ năm). Giá trị 13 chữ số theo mili giây được hiểu là giây render thành ngày khoảng năm 56,000 SCN. Cả hai lỗi đều nhìn thấy ngay khi timestamp được chuyển đổi - dùng Convert Milliseconds to Date để kiểm tra độ hợp lý, hoặc Get Current Time in Milliseconds để so sánh với hiện tại.
ISO 8601: định dạng trao đổi dễ đọc
ISO 8601 là định dạng ngày-giờ đọc được cho con người mà máy móc cũng đồng ý. Dạng chính tắc trông giống: 2026-04-18T12:17:06.520Z. Các phần:
- Ngày:
2026-04-18(YYYY-MM-DD, luôn theo thứ tự này). - Dấu ngăn:
T(chữ T giữa ngày và giờ). - Giờ:
12:17:06.520(HH:MM:SS.sss, 24 giờ). - Múi giờ:
Zcho UTC, hoặc offset như+07:00/-05:30cho các múi khác.
ISO 8601 rõ ràng (không có nhầm lẫn ngày theo vùng như 04-18 vs 18-04), sắp xếp được như chuỗi đơn giản (thứ tự ký tự khớp với thứ tự thời gian khi múi giờ giống nhau), và được mọi parser hiện đại hỗ trợ. Nếu bạn kiểm soát API đang xây dựng, hãy ưu tiên chuỗi ISO 8601 hơn số epoch Unix thô - chúng mang múi giờ một cách rõ ràng, loại bỏ cả một lớp bug.
RFC 2822: định dạng email và HTTP cũ
RFC 2822 (và HTTP-date gần giống từ RFC 7231) trông như Sat, 18 Apr 2026 12:17:06 +0000. Đây là định dạng bạn sẽ thấy trong header Date: của email, header HTTP Last-Modified, và một số API web cũ hơn. Nó đọc được nhưng không sắp xếp được như chuỗi đơn giản (tiền tố ngày trong tuần phá vỡ thứ tự ký tự), nên các hệ thống ngày càng trả về ISO 8601 cùng hoặc thay vì RFC 2822. Khi bạn cần tạo RFC 2822 thủ công, hãy dùng thư viện chứ không tự xây dựng chuỗi - tên ngày trong tuần và viết tắt tháng nhạy cảm với locale và dễ sai.
UTC vs giờ địa phương: gốc của hầu hết bug timestamp
Timestamp epoch Unix luôn là UTC; chuỗi ISO 8601 có thể là UTC (Z) hoặc bất kỳ offset nào; RFC 2822 gần như luôn mang offset. Nhưng khi một chương trình hiện timestamp, nó thường chuyển sang múi giờ địa phương của máy đang hiện.
Điều này tốt cho một người dùng duy nhất nhưng gây hỗn loạn trong ba kịch bản:
- Chia sẻ timestamp trong chat. "Deploy xảy ra lúc 14:00" là mơ hồ - 14:00 của ai? Dán giá trị ISO 8601 (
2026-04-18T14:00:00+07:00) hoặc nêu rõ múi giờ. - Log từ nhiều server. Đặt mọi server theo UTC. Luôn luôn. Bộ gộp log và công cụ phản ứng sự cố giả định UTC; trộn múi giờ trong log là cách nhanh nhất để quy sai chuỗi nhân-quả.
- Lịch hướng tới người dùng. Lưu thời gian sự kiện theo UTC (hoặc múi giờ nguồn của sự kiện với offset rõ ràng) và chuyển đổi lúc hiển thị. Đừng lưu "7pm" không có múi giờ; "7pm" trong phiên của một người dùng có thể là 4pm với người khác.
Ba bẫy thường gặp (và cách bắt chúng)
1. Timestamp số nguyên vs chuỗi trong JSON. JSON.parse của JavaScript sẽ tạo một số cho 1776495426520 - nhưng nếu API trả cùng timestamp đó dưới dạng chuỗi "1776495426520", bất kỳ mã downstream nào làm toán trên nó sẽ chuyển ngầm. Luôn kiểm tra kiểu trước khi truyền sang new Date().
2. Tháng 0-11 trong JavaScript Date. new Date(2026, 3, 18) là 18 tháng 4 năm 2026, không phải 18 tháng 3 năm 2026. Tháng đếm từ 0 nhưng ngày và năm đếm từ 1. Ưu tiên constructor ISO 8601 (new Date("2026-04-18")) theo đếm tự nhiên.
3. Chuyển DST. Vào đêm "tiến lên", 2:30 sáng giờ địa phương không tồn tại; vào đêm "lùi xuống", 1:30 sáng xảy ra hai lần. Nếu hệ thống của bạn lưu chuỗi giờ địa phương, những khoảnh khắc đó tạo ra timestamp không thể hoặc trùng lặp. Lưu UTC loại bỏ vấn đề; các thư viện Date như Luxon hay date-fns-tz xử lý chuyển đổi một cách rõ ràng.
Công cụ liên quan
- Convert Milliseconds to Date - dán timestamp, nhận ngày định dạng UTC và địa phương.
- Get Current Time in Milliseconds - đọc epoch trực tiếp cập nhật mỗi giây.
- MD5 Converter - băm chuỗi cho checksum hoặc khóa khử trùng lặp.
- JSON Parser - kiểm tra phản hồi API chứa trường timestamp.
- Current millis - timestamp Unix theo thời gian thực tính bằng mili giây - hướng dẫn bổ sung giải thích cách đọc giá trị epoch hiện tại.
- Số dài này là mili giây hay giây? - dùng khi bạn nhận được một số lạ và cần xác nhận độ chính xác trước khi xử lý.