Khi làm việc với DateTime giữa Python và JavaScript, có 2 khác biệt căn bản rất dễ gây bug nếu không lưu ý:
1. Chỉ số tháng (Month Index) - Khác biệt lớn nhất
| Ngôn ngữ | Khoảng giá trị tháng | Tháng 1 (January) | Tháng 12 (December) |
|---|---|---|---|
| JavaScript | 0 - 11 | 0 | 11 |
| Python (datetime) | 1 - 12 | 1 | 12 |
Ví dụ: Tuple (2017, 11, 1)
- Python:
datetime(2017, 11, 1)= 1 Tháng 11 Năm 2017 - JavaScript:
new Date(2017, 11, 1)= 1 Tháng 12 Năm 2017 (vì 11 = tháng 12)
2. Múi giờ mặc định (Default Timezone)
| Ngôn ngữ | Mặc định | Ghi chú |
|---|---|---|
| Python (datetime.datetime) | Naive datetime (không có tzinfo) | Thường được coi là UTC hoặc local tuỳ context. Khuyên dùng timezone.utc. |
| JavaScript (Date) | Local timezone của trình duyệt/máy chủ | new Date() dùng múi giờ hệ thống. Date.UTC() dùng UTC. |
Cách xử lý để đồng bộ (Best Practices)
Khi chuyển từ Python -> JavaScript
- Chuyển tháng: Python month (1-12) -> JS month (0-11):
jsMonth = pyMonth - 1. - Chuẩn hóa sang UTC ISO 8601 (Khuyên dùng nhất):
# Python from datetime import datetime, timezone dt = datetime(2017, 11, 1, 10, 30, tzinfo=timezone.utc) iso_string = dt.isoformat() # "2017-11-01T10:30:00+00:00" # JavaScript const date = new Date("2017-11-01T10:30:00+00:00"); // Parse đúng UTC // Hoặc dùng Date.UTC() const utcTimestamp = Date.UTC(2017, 10, 1, 10, 30); // Tháng 11 -> index 10
Khi chuyển từ JavaScript -> Python
- Lấy timestamp (ms since epoch):
const ts = date.getTime();(luôn UTC). - Python:
datetime.fromtimestamp(ts / 1000, tz=timezone.utc). - Hoặc parse ISO string:
datetime.fromisoformat(iso_str.replace('Z', '+00:00'))(Python 3.7+).
Tóm tắt quy tắc an toàn
- Luôn truyền ngày giờ dưới dạng ISO 8601 string có timezone (ví dụ:
2023-10-25T14:30:00Zhoặc+00:00) giữa Python và JS. - Không bao giờ truyền tuple/object năm/tháng/ngày/giờ/phút/giây riêng lẻ giữa 2 ngôn ngữ.
- Nếu buộc phải dùng constructor số: Nhớ trừ 1 cho tháng khi sang JS, cộng 1 khi sang Python.
- Sử dụng thư viện chuyên biệt: Python
pendulum,arrow; JSdate-fns,luxon,dayjs(hỗ trợ UTC tốt).
Kết luận: Khác biệt tháng (0-based vs 1-based) và timezone mặc định (Local vs Naive/UTC) là 2 "cái bẫy" lớn nhất. Luôn dùng ISO 8601 UTC string để trao đổi dữ liệu ngày giờ giữa Python và JavaScript.