Time format - quan1997ap/angular-app-note GitHub Wiki
1. UTC : Coordinated Universal Time
- UTC không phải là múi giờ
- GIờ UTC được viết bằng bốn chữ số sau:
- Hai số chỉ giờ từ 00 tới 23
- Hai số chỉ phút từ 00 tới 59
- Không có dấu giữa các số này. Ví dụ 3 giờ 8 phút chiều được viết là 1508.
Ví dụ:
Thế giới được chia thành khoảng 24 múi giờ
VietNam là UTC + 7 : UTC đi chậm hơn so với Việt Nam 7 tiếng đồng hồ.
Giờ của Việt Nam là +7 mà giờ UTC là + 0 => khi giờ UTC là 0h30′ thì giờ Việt Nam sẽ là 7h30′.
2. GMT : Greenwich Mean Time - Giờ chuẩn Greenwich
- GMT là múi giờ
3. So sánh GMT vs UTC
- Chênh lệch thời gian giữa UTC và GMT nằm trong các phân số của giây ( Do cách tính toán khách nhau)
- Vì vậy, đối với các mục đích chung, cả hai lần được coi là như nhau.
4. ISO 8601 - Tiêu chuẩn định dạng thời gian
Chú ý: Ngày và giờ được kết nối bằng chữ "T" và được viết. Múi giờ được biểu thị là "+09:00" dưới dạng thời gian chênh lệch so với UTC và trong trường hợp UTC, nó được biểu thị là "Z".
VD: https://dencode.com/en/date/iso8601
2022-12-27T06:59:18.000Z [ISO 8601] = 2022-12-27T13:59:18+07:00 [UTC]
5. RFC 3339 - Tiêu chuẩn định dạng thời gian
Chú ý:
- Đặt kí tự Z trong datetime nghĩa là timezone = UTC+0 ( Zulu timezone ) nó tương đương với việc viết +00:00 trong RFC 3339`
- RFC 3339 dựa trên format của ISO 8601. Điểm khác biệt là RFC cho phép thay thế "T" = khoảng trắng
VD1: VD về việc đặt timezone
2019-10-12T07:20:50.52Z (UTC+0) = 2019-10-12T07:20:50.52+00:00 (UTC+0)
2019-10-12T14:20:50.52+07:00 (UTC+7)
2019-10-12T03:20:50.52-04:00 (UTC-4)
VD2: Convert
#This is our datetime stored in DB
2019-10-12T07:20:50.52Z
#This is how it should be converted to UTC+7
2019-10-12T14:20:50.52+07:00
So sánh ISO 8601 với RFC 3339
- ISO 8601 uses the “T” character to separate the date and time. In RFC 3339, you can replace the “T” character with only using space.
# This is acceptable in ISO 8601 and RFC 3339 (with T)
2019-10-12T07:20:50.52Z
# This is only accepted in RFC 3339 (without T)
2019-10-12 07:20:50.52Z
6. Dùng gì và dùng như nào
Câu hỏi?
Trên MySQL thì start_date và end_date của record là 2023-02-10 và 2023-02-14
Nhưng khi API (NodeJS) response là 2023-02-09 17:00 và 2023-02-13 17:00 (UTC + 7)
Vì response như v nên khi lấy dữ liệu đi gọi API khác thì request body là 2023-02-09 và 2023-02-13 🙁
Lí tưởng nhất là luôn đính kèm timezone (tz chứ không phải offset nhé, mình sẽ nói ở phía sau) với datetime trong tất cả các bước:
- khởi tạo: dùng Date object + Intl api
- truyền dẫn: dùng iso8601/rfc3339 + tz
- lưu trữ: dùng datatype datetime with tz hoặc tương đương.
Thiếu tz hay offset sẽ buộc parser phải fallback về local tz và dẫn đến sai lệch, như trường hợp của bạn theo suy đoán thì date 2023-02-10T00:00:00 được lấy ra ở UTC+7 (tz của server?) và trả về ở UTC -> lùi 7 tiếng, format của response có vẻ không có tz indicator nên client tự động ép local tz của browser là UTC+7 vào -> bạn có giá trị sai là 2023-02-09T17:00:00+07:00.
Offset hay Timezone ?
Thường thì chỉ cần có offset là đủ nếu người dùng đến từ 1 múi giờ cố định như vn. Tuy nhiên nếu người dùng đến từ các nước có đổi giờ DST thì lại khác. Ví dụ ở tz Europe/Paris, mùa hè là UTC+2 nhưng mùa đông lại là UTC+1, giả sử người dùng hẹn giờ gửi report vào 2023-10-29T00:00:00+02:00 (giờ mùa hè) và hẹn gửi nhắc lại sau đó 1 ngày, nếu phía server không có thông tin về tz mà chỉ dùng offset +02:00 để lên lịch thì cái nhắc lại sẽ được gửi vào 2023-10-30T00:00:00+02:00, tức 2023-10-29T23:00:00:00+01:00, sớm hơn 1 tiếng so với yêu cầu do rạng sáng ngày 29 đổi sang giờ mùa đông. Cho nên ở trường hợp này tz quan trọng hơn offset. Lưu ý là định dạng iso8601 / rfc 3339 chỉ có offset mà không có tz, nếu muốn đính kèm thì phải để bên ngoài hoặc chế format như cách java làm (2023-02-10T12:34:56+01:00[Europe/Paris])
Thống nhất dùng UTC / unix timestamp cho tất cả các bên ?
Nhiều comment ở trên khuyên cách này. Tôi thì khuyên bạn đừng làm thế. Giả sử người dùng của bạn ở UTC+7 chọn start date là 2023-02-10, đưa về UTC nó sẽ là 2023-02-09T17:00:00Z, khi gửi lên server nếu muốn tính đúng ngày 10/02 bạn vẫn phải đưa value này trở lại UTC+7. Ở đây server dựa vào quy ước ngầm về múi giờ để tính toán, coi mọi giá trị đều thuộc UTC+7, như vậy bước chuyển về UTC ở cả 2 đầu gửi và nhận đều là thừa, việc bạn cần làm chỉ là gửi kèm tz thôi (cf điểm 1). Thêm vào đó giả sử có người dùng ở UTC+8 chọn start date 2023-02-10, bạn đưa về UTC là 2023-02-09T16:00:00Z, phía server dựa vào quy ước sẽ đưa về +7 là 2023-02-09T23:00:00+07:00 và lấy ra ngày 2023-02-09, từ góc nhìn của user thì ngày này sai lè đúng không ?