13 điểm bởi GN⁺ 2026-03-12 | 7 bình luận | Chia sẻ qua WhatsApp
  • 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

 
jeeeyul 2026-03-12

Độ 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 long cũ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.

 
tsboard 2026-03-12

Cuối cùng cũng đến! Vui quá!!

 
shakespeares 2026-03-12

Cuối cùng cũng xong!!

 
roxie 2026-03-12

ZonedDateTime...? Chẳng lẽ là cậu..!

 
sea715 2026-03-12

Cuối cùng cũng vậy

 
click 2026-03-12

time.h của C -> java.util.Date của Java -> Date của js

joda-time của Java -> JSR 310 -> java.time
-> moment.js -> Temporal của js

Đúng là một dòng chảy như vậy nhỉ

 
GN⁺ 2026-03-12
Ý kiến trên Hacker News
  • Tôi rất thích việc Temporal buộc người dùng phải xử lý đúng độ phức tạp của việc quản lý thời gian
    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
    • Nói về mặt kỹ thuật thì có lẽ việc sửa lỗi DST lúc 3 giờ sáng hiếm khi xảy ra ngoài Chủ nhật
  • Tôi cũng đã gần như khổ sở suốt 10 năm với chuyện parse ngày ISO8601 trong Python
    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
    • Thật lòng rất biết ơn. Việc parse ngày bằng cách khác ngoài fromisoformat giờ cảm thấy quá không trực quan
      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
  • Việc Firefox có thể triển khai Temporal ngay từ giai đoạn đặc tả là nhờ André Bargull (Anba),
    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
  • Temporal là một bước tiến lớn, nhưng tôi vẫn không thích API này
    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
    • Đây là thiết kế có chủ đích. Các kiểu Temporal có thể serialize, nhưng không được tự động khôi phục bằng JSON.parse
      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
    • Tôi cũng hay gặp đúng vấn đề này. Việc prototype biến mất sau JSON.parse/stringify là chuyện rất phổ biến
      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
    • Thực ra instance Date của JavaScript cũng gặp cùng vấn đề
      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
    • Mọi đối tượng Temporal đều có thể serialize/deserialize dễ dàng bằng .toString()Temporal.from()
    • Tôi nghĩ việc thay đổi JSON.parse để nó tự tạo đối tượng Temporal là cách tiếp cận quá đà
      Cũng như với Date
      serialize: instant.toJSON()
      deserialize: Temporal.Instant.from(jsonDate)
      
      Xử lý tường minh như vậy mới là đúng
  • Tôi thực sự rất vui vì Temporal đã được thông qua
    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
  • Sẽ rất thú vị nếu bài viết cũng nhắc đến hành trình cải tiến API thời gian của Java (Joda-Time → JSR 310 → Java 8)
    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
    • Đúng hơn thì Joda đã ảnh hưởng đến Moment.js, rồi điều đó lại được phản ánh vào các cuộc thảo luận của TC39
      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
    • Đúng vậy, JavaScript cũng đã mang về từ Java một phiên bản Date tệ hơn
      Có thể xem thêm trong chuỗi HN này
  • Câu “thời Mocha, Ken Smith đã port code Date của Java sang C” nghe rất buồn cười
    Vì util.Date của Java tự nó vốn gần như là bản port của API time.h trong C
  • Tôi bật cười khi thấy Safari chỉ hỗ trợ Temporal một phần
    Có vẻ giờ Safari đã trở thành người kế thừa tinh thần của IE
    • Safari chậm đưa tính năng mới vào, nhưng dù sao vẫn đang đều đặn triển khai
      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ự
    • Có khi đến năm 2026, Safari trên di động vẫn sẽ không có trình chọn ngày gốc
  • Tôi ước Temporal có kiểu interval
    const D = new Temporal()
    const t = new Interval({minutes:5})
    const v = D.add(t)
    
    • Đó là Duration
      const D = Temporal.PlainDate.from("2020-06-16");
      const t = Temporal.Duration.from({ day: 1 });
      const v = D.add(t) // 2020-06-17
      
      Xem tài liệu MDN
    • Đúng rồi, cái đó được gọi là Duration
  • Cảm ơn đội ngũ đã du hành thời gian ở tốc độ 1x trong suốt 9 năm vì điều này