Định dạng nào cho timestamp trong JSON
Kết luận: Số epoch và chuỗi ISO đều có điểm đánh đổi, nhưng trộn lẫn chúng mới là thứ thực sự làm hỏng mọi việc. Hãy dùng ISO 8601 kèm offset, lưu theo UTC, hiển thị theo múi giờ của người dùng.

Tóm lại: hãy dùng ISO 8601 kèm offset rõ ràng trên đường truyền, lưu UTC với hậu tố Z, và chỉ chuyển đổi ở thời điểm hiển thị; nếu bạn chọn số epoch, hãy cố định giây hay mili giây trên toàn hệ thống và đặt đơn vị vào tên trường.
Tại sao 2026-10-30 14:30:00 là chưa đủ
Chuỗi đó không mang múi giờ. 14:30 ở Shanghai và 14:30 ở London cách nhau tám giờ, và không có cách nào biết ý là cái nào. new Date('2026-10-30 14:30:00') phân tích theo múi giờ địa phương của runtime, nên máy chủ và trình duyệt suy ra hai thời điểm khác nhau từ một payload — kiểu lỗi không bao giờ tái hiện được.
Một 2026-10-30 trần không phải một thời điểm. Ổn cho ngày sinh và kỳ thanh toán, sai cho thời gian tạo.
Hai định dạng dùng được
Chuỗi ISO 8601
{
"createdAt": "2026-10-30T14:30:00+08:00",
"updatedAt": "2026-10-30T06:30:00Z"
}
Dễ đọc, sắp xếp được khi định dạng nhất quán, chính xác đến mili giây nếu cần, và tự mô tả.
Số epoch
{ "createdAt": 1793519400 }
Gọn và không nhập nhằng, nhưng khó đọc, và giây so với mili giây là mối nguy thường trực. Nếu chọn epoch, hãy chuẩn hóa đơn vị và đặt nó vào tên trường: createdAtMs an toàn hơn nhiều so với createdAt.
Những quy ước nên chốt sớm
| Hạng mục | Quy ước |
|---|---|
| Định dạng trên đường truyền | ISO 8601 với Z hoặc +08:00 |
| Múi giờ lưu trữ | UTC, để giờ mùa hè không bao giờ xen vào |
| Độ chính xác | Mili giây là đủ |
| Đặt tên trường | createdAt, updatedAt, expiresAt |
| Ngày thuần | Một trường date riêng, ví dụ birthday: "1990-01-01" |
| Thời lượng | Số nguyên kèm đơn vị, ví dụ timeoutMs: 3000 |
Hiển thị
new Intl.DateTimeFormat('en-GB', {
dateStyle: 'medium',
timeStyle: 'short',
timeZone: 'Europe/London',
}).format(new Date('2026-10-30T06:30:00Z'));
Hãy chỉ định timeZone rõ ràng khi việc hiển thị không được theo thiết bị. Dựa vào mặc định của trình duyệt là đúng cho thời gian hướng tới người dùng và sai cho báo cáo.
Ba lỗi lặp đi lặp lại
Ngày trần được phân tích thành nửa đêm UTC. Theo đặc tả ECMAScript, chuỗi chỉ có ngày là UTC trong khi chuỗi ngày-giờ là giờ địa phương. Sự không nhất quán đó là nguồn lỗi lệch một ngày đáng tin cậy.
Múi giờ của cơ sở dữ liệu không khớp với bộ tuần tự hóa. datetime của MySQL không có múi giờ; ghi giờ địa phương, đọc như UTC, và mọi thứ lệch đi theo offset.
Giờ mùa hè. Lưu giờ địa phương trong tương lai tạo ra những thời điểm không tồn tại hoặc xuất hiện hai lần. UTC không có khoảng trống như vậy.
Hỏi đáp
Nên chọn ISO 8601 hay số epoch thế nào?
Dùng ISO 8601 khi con người đọc payload, khi bạn muốn thứ tự sắp xếp từ vựng, hoặc khi giá trị phải mang múi giờ của chính nó; cái giá là khoảng một chục byte thừa và một thư viện phân tích. Dùng số epoch khi độ gọn và xử lý xuyên ngôn ngữ đơn giản quan trọng hơn, nhưng hãy cố định giây so với mili giây trên toàn hệ thống và nói rõ trường chứa đơn vị nào.
Ngày trần và timestamp có nên dùng chung một trường không?
Không. Một 2026-10-30 trần là một ngày lịch không có giờ và không có múi giờ, trong khi trường timestamp được kỳ vọng mang một thời điểm chính xác. Hãy giữ ngày sinh và kỳ thanh toán trong một trường date riêng, và dùng trường At theo ISO 8601 cho thời gian tạo hoặc cập nhật.