- Chuẩn mới Temporal API nhằm thay thế tận gốc những giới hạn của đối tượng Date trong JavaScript đã đạt ECMAScript Stage 4 sau 9 năm phát triển
- Temporal cung cấp kiểu bất biến (immutable), hỗ trợ múi giờ và lịch một cách tường minh, cùng độ chính xác tới nanogiây, loại bỏ sự mơ hồ và lỗi của Date hiện tại
- Nhiều tổ chức như Bloomberg, Igalia, Microsoft, Google, Mozilla đã cùng hợp tác thiết kế đặc tả và hiện thực hóa, đồng thời hiện thực thư viện dùng chung
temporal_rs dựa trên Rust để cộng tác đa engine
- Temporal hỗ trợ chính xác các phép toán thời gian và xử lý lịch quốc tế thông qua các kiểu chi tiết như ZonedDateTime, Instant, PlainDate/Time, Duration
- Chuẩn này, vốn giải quyết vấn đề kéo dài suốt 30 năm, được xem là một ví dụ thành công về hợp tác và đổi mới mở trong hệ sinh thái JavaScript
Vấn đề xử lý thời gian trong JavaScript và sự xuất hiện của Temporal
- Đối tượng Date hiện tại vốn được port gần như nguyên bản từ Date của Java năm 1995, và suốt nhiều thập kỷ đã trở thành nguồn gốc của lỗi do tính có thể thay đổi, cách tính tháng không nhất quán, và việc parse mơ hồ
- Ví dụ: lỗi tính cuối tháng khi dùng
setMonth, hoặc kết quả không đồng nhất giữa các trình duyệt khi parse chuỗi gần giống ISO
- Từ thập niên 2010 trở đi, khi ứng dụng web ngày càng phức tạp, những giới hạn của Date càng trở nên nghiêm trọng hơn
- Các nhà phát triển đã dùng thư viện bên ngoài như Moment.js để khắc phục, nhưng lại phát sinh kích thước bundle lớn hơn và gánh nặng bảo trì
- Năm 2017, Maggie Johnson-Pint đã đệ trình đề xuất Temporal lên TC39, mở đầu cho quá trình thảo luận chuẩn hóa
Sự hợp tác giữa TC39 và ngành công nghiệp
- Temporal bắt đầu từ Stage 1 vào năm 2018 và sau 9 năm đã đạt Stage 4 (chuẩn hóa)
- Bloomberg tham gia tích cực nhằm giải quyết các vấn đề về múi giờ và độ chính xác trong môi trường JavaScript quy mô lớn
- Yêu cầu gồm: múi giờ tùy biến, độ chính xác lịch sử theo IANA, và độ chính xác ở mức nanogiây
- Dự án được triển khai cùng với Igalia, Microsoft, Google, Mozilla và nhiều bên khác trong cả thiết kế đặc tả lẫn hiện thực
- Nhiều kỹ sư như Philipp Dunkel, Ujjwal Sharma, Philip Chimento, Shane Carr, Justin Grant đã tham gia với vai trò champion
Các kiểu và tính năng chính của Temporal
- Temporal.ZonedDateTime: biểu diễn thời điểm bất biến có kèm múi giờ, lịch và hiệu chỉnh DST một cách tường minh
- Ví dụ: khi chuyển DST ở London khiến
01:30 không tồn tại, giá trị sẽ tự động được hiệu chỉnh thành 02:30
- Temporal.Instant: biểu diễn một thời điểm tuyệt đối không gắn với múi giờ hay lịch, hỗ trợ độ chính xác ở mức nanogiây
- Có thể chuyển cùng một thời điểm sang nhiều múi giờ khác nhau
- PlainDate / PlainTime / PlainDateTime / PlainYearMonth / PlainMonthDay: các kiểu “đồng hồ treo tường” không gắn múi giờ
- Phù hợp để hiển thị hoặc tính toán ngày giờ đơn giản
- Temporal.Duration: biểu diễn khoảng thời gian, có thể chuyển đổi giữa nhiều đơn vị (
total({ unit: "second" }))
- Hỗ trợ lịch: thực hiện chính xác các phép toán với lịch phi Gregory như lịch Hebrew
Quá trình hiện thực và chuẩn hóa
- Temporal là phần bổ sung đặc tả lớn nhất trong lịch sử ECMAScript, với khoảng 4.500 ca kiểm thử
- Hiện thực dùng chung
temporal_rs dựa trên Rust đã được phát triển để nhiều engine như V8, Boa cùng sử dụng
- Ưu điểm: giảm rào cản tham gia, thuận lợi cho bảo trì dài hạn, và nâng cao chất lượng mã nguồn
- Trong giai đoạn 2024–2025,
temporal_rs đã vượt qua 100% bài kiểm thử và được đánh giá là một ví dụ thành công của hợp tác đa engine
Tình trạng hỗ trợ và các bài toán tiếp theo
- Temporal hiện đã được hỗ trợ trong Firefox 139, Chrome/Edge 144, TypeScript 6.0 Beta
- Safari vẫn đang ở giai đoạn technical preview, còn Node.js 26 được lên kế hoạch hỗ trợ
- Bài toán tiếp theo là tích hợp với Web API
- Ví dụ: hỗ trợ kiểu
Temporal trong các phần tử form như <input type="date">
- Xem xét khả năng thay thế
DOMHighResTimeStamp (ví dụ dùng Temporal.Now.instant())
Thành quả của hợp tác và đổi mới mở
- Temporal là một chuẩn được hoàn thiện thông qua 9 năm hợp tác giữa nhiều tổ chức, với sự tham gia của
- Microsoft, Google, Mozilla, Bloomberg, Igalia, Boa và nhiều bên khác
temporal_rs là ví dụ thành công của mô hình hạ tầng dùng chung, chứng minh rằng
- có thể giảm chi phí hiện thực trùng lặp, cải thiện tính nhất quán và thúc đẩy đổi mới
- Temporal không chỉ là một cải tiến API đơn thuần mà còn được xem là bằng chứng cho thấy cộng đồng JavaScript đã cùng nhau giải quyết khoản nợ kỹ thuật dài hạn
- Sau 30 năm, JavaScript cuối cùng đã có được API ngày giờ hiện đại
7 bình luận
Độ phức tạp của việc tính toán thời gian không chỉ là vấn đề định dạng, mà phần lớn còn bắt nguồn từ triết học của nhân loại, độ chính xác của thiên văn học và văn hóa. Việc tính toán thì chỉ với
longcũng đã dễ rồi. Trong lịch sử, có rất nhiều múi thời gian được quy định với những giai đoạn đặc biệt mà 1 + 1 không bằng 2, và phần lớn điều này bắt nguồn từ các loại lịch pháp, nơi ngày tháng thay đổi theo vị trí như góc giữa Mặt Trời và bề mặt Trái Đất. Trong những trường hợp như vậy, âm dương lịch của Hàn Quốc thậm chí chưa từng là đối tượng được đem ra thảo luận.Và đó là điều do Viện Nghiên cứu Thiên văn Hàn Quốc quyết định.
Cuối cùng cũng đến! Vui quá!!
Cuối cùng cũng xong!!
ZonedDateTime...? Chẳng lẽ là cậu..!
Cuối cùng cũng vậy
time.hcủa C ->java.util.Datecủa Java ->Datecủa jsjoda-timecủa Java -> JSR 310 ->java.time-> moment.js ->
Temporalcủa jsĐúng là một dòng chảy như vậy nhỉ
Ý kiến trên Hacker News
Việc phân biệt giữa instant và datetime dựa trên lịch giúp gần như ngăn được các lỗi thường gặp với Date
Hơi dài dòng một chút, nhưng vẫn tốt hơn nhiều so với bị gọi dậy lúc 3 giờ sáng để sửa lỗi DST
Vấn đề bắt đầu từ năm 2012 cuối cùng cũng có lời giải trong thư viện chuẩn
Có thể xem thảo luận liên quan trong chuỗi Google Groups này
Trước đây tôi dùng ciso8601, nhưng từ khi có trong chuẩn thì mọi thứ đơn giản và ổn định hơn nhiều
và điều đặc biệt ấn tượng là anh ấy thực ra đã tự mình triển khai toàn bộ với tư cách tình nguyện viên
Tôi chia sẻ code giữa client và server nên cố gắng tách biệt dữ liệu và logic một cách nghiêm ngặt
Tôi muốn giữ toàn bộ dữ liệu ở dạng JSON thuần để dễ serialize/deserialize, nhưng các đối tượng Temporal lại là instance của class có thuộc tính hàm nên khá bất tiện
Tôi nghĩ cách của date-fns, tức áp dụng các hàm thuần lên các đối tượng chỉ chứa dữ liệu, sẽ tốt hơn
Nhà phát triển phải tự tái tạo đúng đối tượng từ chuỗi ISO
Nếu tự động hóa thì có nguy cơ xử lý sai kiểu dữ liệu
Ví dụ Temporal.Instant reviver trong tài liệu có thể hữu ích
Nhưng tôi nghĩ lựa chọn của nhóm Temporal là đúng. Với logic ngày giờ, an toàn kiểu dữ liệu quan trọng hơn cách tiếp cận dữ liệu thuần + hàm
Gắn các phép toán với đối tượng giúp tránh việc PlainDate vô tình bị xử lý như ZonedDateTime
Trong những chỗ như tRPC, chỉ cần thêm một lớp mỏng để chuyển đổi bằng Temporal.from() và toString() ở ranh giới là đủ
Có hơi phiền một chút, nhưng vẫn tốt hơn là từ bỏ an toàn kiểu dữ liệu
Date.toJSON thì có, nhưng khi parse JSON vẫn phải tự đổi chuỗi trở lại thành Date
Temporal cũng vậy, và date-fns cuối cùng cũng xử lý instance Date gốc
.toString()vàTemporal.from()Cũng như với Date Xử lý tường minh như vậy mới là đúng
Xin chúc mừng tất cả những champion đã nỗ lực trong thời gian dài
Tôi đã có quãng thời gian rất thú vị khi làm temporal_rs trong vài năm qua
Vì đề xuất mang tính cấp tiến của JavaScript xuất hiện vào năm 2018, tôi cũng tò mò liệu cách tiếp cận của Java có ảnh hưởng phần nào hay không
TC39 có tham khảo tiền lệ từ các ngôn ngữ khác, nhưng đi đến đồng thuận theo hướng tối ưu cho JavaScript
Tôi nghĩ API lần này là bản triển khai hoàn thiện nhất do các chuyên gia JS thiết kế trong suốt 9 năm
Có thể xem thêm trong chuỗi HN này
Vì util.Date của Java tự nó vốn gần như là bản port của API time.h trong C
Có vẻ giờ Safari đã trở thành người kế thừa tinh thần của IE
Vấn đề của IE không phải là chậm, mà là đứng yên ở vị thế thống trị
Giờ Chrome mới đang ở vị trí đế chế đó, và thực ra Safari cùng Firefox lại càng cần thiết hơn
Sự gia tăng của các website chỉ dành cho Chrome mới là vấn đề thật sự