Cuối cùng JavaScript Dates sắp được sửa
(docs.timetime.in)- Một trong những thay đổi đáng chú ý nhất gần đây của ECMAScript là đề xuất Temporal
- API này đã có thể sử dụng ngay thông qua polyfill do nhóm FullCalendar cung cấp
- Một trong những ưu điểm lớn nhất của API này là cuối cùng đã có một đối tượng native để biểu diễn "Zoned Date Time"
Zoned Date Time là gì?
- Khi xử lý ngày tháng theo cách con người sử dụng, chúng ta thường nói về ngày và giờ mà bỏ qua múi giờ
- Tuy nhiên, đối tượng "Date" của JavaScript chỉ xử lý các con số nên ý nghĩa ban đầu của ngày tháng bị mất đi
- Ví dụ, khi muốn ghi lại thời điểm thanh toán bằng thẻ, nhiều người có thể dùng đoạn mã như sau
const paymentDate = new Date('2024-07-20T10:30:00'); - Trình duyệt sẽ tính mili giây dựa trên múi giờ của người dùng (CET). Nhưng thông tin đã lưu có thể được diễn giải khác nhau tùy theo múi giờ
- Ngoài thực tế rất quan trọng là trong JavaScript, ngày tháng không dựa trên UTC mà là POSIX, nơi leap second bị bỏ qua hoàn toàn, còn có vấn đề là nếu chỉ còn lại con số thì ý nghĩa gốc của ngày tháng sẽ biến mất
- Nhiều người nghĩ rằng chỉ cần làm việc với UTC hoặc truyền ngày tháng ở định dạng ISO là an toàn, nhưng điều đó không đúng vì vẫn có thể bị mất thông tin
UTC là chưa đủ
- Ngay cả khi làm việc với định dạng ISO, khi hiển thị ngày tháng vẫn thiếu thông tin về múi giờ
- Hàm chuyển timestamp thành ngày tháng mà con người có thể đọc được không phải là injective (hàm đơn ánh)
- Ví dụ, khi bạn đi từ Madrid sang Sydney rồi quay về, vấn đề múi giờ trong lịch sử giao dịch ngân hàng có thể gây ra nhầm lẫn
Giới thiệu Temporal API
- Temporal API giới thiệu đối tượng Temporal.ZonedDateTime để biểu diễn ngày và giờ kèm múi giờ
- API này đề xuất một phần mở rộng của RFC 3339, đưa ra tiêu chuẩn để serialize và deserialize ngày tháng dưới dạng chuỗi
1996-12-19T16:39:57-08:00[America/Los_Angeles]- Chuỗi này biểu thị 16 giờ 39 phút 57 giây ngày 19 tháng 12 năm 1996,
- offset so với UTC là -08:00 (giờ chuẩn Thái Bình Dương PST, nơi Los Angeles thuộc về)
- đồng thời chỉ định thêm múi giờ liên quan ("giờ chuẩn Thái Bình Dương") để các ứng dụng có nhận thức về múi giờ có thể cân nhắc
- Hỗ trợ nhiều hệ lịch khác nhau (ví dụ: Phật lịch, Trung Quốc, Dangi, Gregory, Hồi giáo, Ba Tư, Nhật Bản, v.v.)
Các phép toán cơ bản
Tạo ngày tháng
- Temporal API cung cấp công cụ mạnh mẽ để xử lý múi giờ
- Ví dụ, khi tạo đối tượng
Temporal.ZonedDateTime, múi giờ được phản ánh chính xác:const zonedDateTime = Temporal.ZonedDateTime.from({ year: 2024, month: 8, day: 16, hour: 12, minute: 30, second: 0, timeZone: 'Europe/Madrid'}); - Nhờ đó có thể giữ được thời gian chính xác ngay cả khi có thay đổi múi giờ hoặc điều chỉnh giờ địa phương như DST
So sánh ngày tháng
- Đối tượng ZonedDateTime cung cấp phương thức
compaređể so sánh hai ZonedDateTime:const one = Temporal.ZonedDateTime.from('2020-11-01T01:45-07:00[America/Los_Angeles]'); const two = Temporal.ZonedDateTime.from('2020-11-01T01:15-08:00[America/Los_Angeles]'); Temporal.ZonedDateTime.compare(one, two); // => -1
Các tính năng tích hợp hữu ích
- Thuộc tính
hoursInDaytrả về số giờ thực tế của ngày đó:Temporal.ZonedDateTime.from('2020-03-08T12:00-07:00[America/Los_Angeles]').hoursInDay; // => 23 (ngày bắt đầu DST)
Chuyển đổi múi giờ
- Có thể thay đổi múi giờ của ZonedDateTime bằng phương thức
withTimeZone:zdt = Temporal.ZonedDateTime.from('1995-12-07T03:24:30+09:00[Asia/Tokyo]'); zdt.withTimeZone('Africa/Accra').toString(); // => '1995-12-06T18:24:30+00:00[Africa/Accra]'
Phép toán số học cơ bản
- Có thể dùng phương thức
.addđể cộng hoặc trừ ngày theo quy tắc DST:zdt = Temporal.ZonedDateTime.from('2020-03-08T00:00-08:00[America/Los_Angeles]'); laterDay = zdt.add({ days: 1 }); // => 2020-03-09T00:00:00-07:00[America/Los_Angeles]
Tính chênh lệch giữa các ngày giờ
- Phương thức
.untiltính khoảng chênh lệch giữa hai thời điểm và trả về đối tượngTemporal.Duration- Ví dụ có thể dùng như
zdt.until(other)
- Ví dụ có thể dùng như
Kết luận
- Temporal API đang tạo ra thay đổi mang tính cách mạng trong cách JavaScript xử lý thời gian
- Bài viết này đã đề cập đến sự khác biệt giữa ngày tháng con người đọc được và ngày tháng UTC, cũng như cách biểu diễn chúng chính xác bằng đối tượng Temporal.ZonedDateTime
- Trong bài tiếp theo, tác giả sẽ khám phá những đối tượng thú vị khác như Instant, PlainDate và Duration
Ý kiến của GN⁺
- Vấn đề xử lý ngày giờ vốn gây khó khăn cho các lập trình viên JavaScript trong thời gian dài có thể sẽ được giải quyết nhờ Temporal API
- API này có thể tự động xử lý các vấn đề về múi giờ và DST, nên rất hữu ích khi phát triển ứng dụng toàn cầu
- Khả năng tương thích với đối tượng
Datehiện có và các vấn đề migration vẫn là những điểm cần cân nhắc TemporalAPI được thiết kế theo hướng rõ ràng, trực quan và còn hỗ trợ nhiều hệ lịch khác nhau, nên cũng rất mạnh về mặt quốc tế hóa- Kỳ vọng rằng thay đổi này sẽ cải thiện đáng kể năng suất của lập trình viên JavaScript
5 bình luận
Cuối cùng cũng tới!
Tham khảo thêm, Deno đã tích hợp sẵn Temporal API.
Quá đã, khi thiết kế dịch vụ toàn cầu thì chuyện ngày tháng lúc nào cũng làm đau đầu.
Cái này mình rất muốn thử một lần.
Thật sự, cuối cùng cũng đến lúc không cần dùng moment hay dayjs nữa sao?
Ý kiến Hacker News
Việc xử lý ngày và giờ trong Javascript rất khó
API mới được kỳ vọng sẽ giải quyết vấn đề múi giờ của JS
Hàm chuyển đổi timestamp thành ngày tháng con người có thể đọc được không phải là đơn ánh
Một câu đùa về đường cong độ khó của việc xử lý thời gian
Nếu dùng nhiều ví dụ về ngày trong tương lai hơn thì bài viết sẽ thuyết phục hơn
Người dùng cảm thấy bất an vì không hiểu cách xử lý thời gian
Có một tiêu chuẩn datetime tốt mới chỉ là một nửa cuộc chiến
Chuỗi ngày ISO cần nắm bắt chính xác thông tin
Câu hỏi về cách xử lý vấn đề này trong Postgres
Thiếu bằng chứng cho thấy Temporal sẽ thực sự được triển khai