DateTime Trong Lập Trình: Best Practice Từ FE Đến BE Và DB
DateTime là một trong những vấn đề tưởng đơn giản nhưng lại có khả năng tạo ra những bug rất khó phát hiện trong hệ thống thực tế.
Một hệ thống có thể hoạt động hoàn toàn bình thường trong môi trường Developer, nhưng khi chạy production lại xuất hiện:
- UI hiển thị lệch vài tiếng.
- API trả về đúng nhưng Frontend hiển thị sai.
- Database lưu
2026-09-18 06:00:00trong khi User nhập15:00. - Report "Today" bị thiếu dữ liệu.
- Cron chạy sai ngày.
- Queue chạy khác timezone với Web.
- Import CSV làm thay đổi ngày giờ.
- Migration từ Legacy sang hệ thống mới làm lệch thời gian.
- Query trực tiếp trên MySQL Client cho kết quả khác với Application.
DATE(created_at)làm query report chậm trên bảng hàng triệu record.
Vấn đề lớn nhất thường không nằm ở DateTime itself.
Vấn đề nằm ở việc hệ thống không xác định rõ DateTime đó đang đại diện cho thời điểm nào, timezone nào và business meaning là gì.
1. Mục Tiêu
Chúng ta sẽ trả lời rõ các câu hỏi:
- Date / Time / DateTime là gì?
- Local Time và UTC khác nhau thế nào?
- Timezone ảnh hưởng đến hệ thống ra sao?
- Nên xử lý DateTime ở đâu: FE, BE hay Database?
- Nên lưu dưới dạng gì?
- Khi nào dùng DATE, DATETIME, TIMESTAMP?
- Khi nào cần UTC, khi nào cần Local Time?
- Làm sao thiết kế hệ thống DateTime ngay từ đầu để tránh bug?
- Xử lý hệ thống Global và hệ thống Nhật Bản như thế nào?
- Query/report trực tiếp trên MySQL Client mà không bị lệch timezone?
2. Trước tiên: DateTime thực sự là gì?
Có một số khái niệm cần phân biệt ngay từ đầu.
| Khái niệm | Ý nghĩa | Ví dụ |
|---|---|---|
| Date | Chỉ ngày | 2026-09-18 |
| Time | Chỉ thời gian | 15:00:00 |
| DateTime | Ngày + giờ | 2026-09-18 15:00:00 |
| Timestamp | Một thời điểm cụ thể trên timeline | 2026-09-18T06:00:00Z |
| ISO 8601 | Định dạng chuẩn quốc tế để biểu diễn Date/Time kèm timezone offset, tránh nhầm lẫn khi truyền dữ liệu giữa các system | 2026-09-18T15:00:00+09:00, 2026-09-19T07:06:30Z Z nghĩa là UTC (Zulu time). |
| UTC | Coordinated Universal Time - Mốc thời gian tham chiếu toàn cầu, không có offset | UTC+00:00, 2026-09-18T08:00:00Z |
| Local Time | Giờ theo một timezone cụ thể | 15:00 JST 15:00 theo giờ Nhật |
| Timezone | Quy tắc offset (+ DST - Daylight Saving Time) xác định giờ địa phương | UTC, Asia/Tokyo, Asia/Ho_Chi_Minh |
| Application Time | Timezone mà framework (Laravel, Node...) config để xử lý DateTime | APP_TIMEZONE=Asia/Tokyo |
| Browser Time | Timezone của máy client, JS Date mặc định dùng cái này |
Intl.DateTimeFormat().resolvedOptions().timeZone |
| Server Time | Timezone của máy chủ ứng dụng | Thường là UTC hoặc Asia/Tokyo |
| Database Time | Timezone cấu hình trong Laravel/PHP, Giờ mà DB engine dùng khi gọi NOW(), phụ thuộc session/global timezone | @@session.time_zone |
| Business Date | "Ngày" theo quy tắc nghiệp vụ (VD: ngày làm việc Nhật Bản, không nhất thiết trùng ngày UTC) | 2026-09-18 |
| Business Time | Mốc giờ có ý nghĩa nghiệp vụ | 09:00 giờ cửa hàng mở |
| Display DateTime | Giá trị được format để hiển thị | 18/09/2026 15:00 |
Một lỗi architecture phổ biến là xem tất cả những giá trị trên như cùng một loại dữ liệu. Thực tế chúng có ý nghĩa khác nhau.
Yêu cầu đăng nhập
Vui lòng đăng nhập để truy cập nội dung này
Additional Resources
Course Guide
Comprehensive PDF guide with examples
GitHub Repository
Example code for all lessons
Discussion
Have a question about this lesson? Post it here and get answers from instructors and peers.
