'Cải tổ' ngày giờ trong JavaScript với Temporal API

JavaScript cuối cùng cũng có công cụ xử lý thời gian chuẩn chỉnh với nhiều tính năng toàn diện và phong phú, Temporal API chắc chắn là sự thay thế vượt trội cho Date object vốn đã cũ kỹ.

Trong JavaScript, Date từ lâu đã là công cụ quen thuộc để xử lý ngày giờ đối với các lập trình viên trong gần 30 năm nay. Tuy nhiên, mức độ 'lâu đời' này không phải thể hiện sự ổn định lâu dài mà là khoảng thời gian 'tồn đọng' những các vấn đề chưa được giải quyết, có thể kể đến như:

  • Các đối tượng trong Date là mutable, có thể bị thay đổi sau khi khởi tạo dễ gây ra lỗi tiềm ẩn
  • Không hỗ trợ múi giờ
  • Việc parsing không nhất quán
  • Tính năng có phần nghèo nàn, không hỗ trợ tính khoảng thời gian (duration), chỉ hỗ trợ lịch Gregorian (lịch dương) và các hàm tính ngày giờ không được linh hoạt

Chính vì thế mà hội dev phải tìm đến những thư viện xử lý ngày giờ chuyên dụng hơn, phổ biến nhất đó là Moment.js. Tuy nhiên, về lâu dài, kích thước bundle của thư viện ngày càng phình to, ảnh hưởng đến hiệu suất của ứng dụng.

Xu hướng hiện nay đang chú trọng nhiều vào việc tối ưu hiệu suất, giảm phụ thuộc vào các thư viện bên ngoài và hướng tới các giải pháp native. Cuối cùng thì JavaScript Temporal cũng đã xuất hiện, một API native đang được thử nghiệm trong năm 2025, hứa hẹn sẽ là công cụ triển vọng trong cách đổi mới việc xử lý thời gian. Hãy cùng khám phá Temporal API và xem các hạn chế tồn đọng được giải quyết như thế nào trong bài viết này nhé!

Upload image

Bài viết đang dựa vào những điểm cập nhật mới nhất về Temporal tính đến tháng 2/2025.

Temporal API là gì?

Temporal là API native mới toanh của JavaScript, ra đời để thay thế hoàn toàn Date vốn cũ kỹ. Với Temporal, việc xử lý thời gian trong JavaScript sẽ hiện đại hóa đáng kể, đặc biệt chính xác đến từng nanosecond, hỗ trợ múi giờ, làm việc với đa dạng lịch (như lịch âm, Do Thái, Hồi giáo). Thiết kế bất biến (immutable) của Temporal cũng sẽ giúp tránh lỗi do thay đổi giá trị ngoài ý muốn.

Bạn có thể trải nghiệm Temporal bằng cách tải Firefox Nightly, tải thư viện @js-temporal/polyfill hoặc nhanh nhất là truy cập vào Proposal Temporal và thử ngay trực tiếp trên Console của DevTools. Ngoài ra, Temporal cũng đã chuẩn bị tài liệu cho khoảng hơn 200 hàm tiện ích cho việc tham khảo, xem chi tiết tại đây.

Khái niệm cốt lõi

Upload image

Minh hoạ về các khái niệm ngày giờ. Nguồn: Proposal Temporal

Trong Temporal, thời gian được chia nhỏ thành các khái niệm như sau:

  • Exact time (thời điểm chính xác): thông qua 2 class Temporal.Instant (chỉ lưu giờ UTC) và Temporal.ZonedDateTime (lưu thêm múi giờ và hệ thống lịch).
// 1. Lấy giờ chính xác
// - Giờ UTC
const instant = Temporal.Instant.from('2025-01-01T12:34:56Z');
instant.toString(); // => "2025-01-01T12:34:56Z"
instant.epochMilliseconds; // => 1735734896000

// - Giờ thêm múi giờ
const zonedDateTime = Temporal.ZonedDateTime.from('2025-01-01T12:34:56[Asia/Saigon]');
zonedDateTime.toString() // => "2025-01-01T12:34:56+07:00[Asia/Saigon]"
  • Wall-clock time (giờ địa phương không múi giờ): thông các class Temporal.PlainDateTime, Temporal.PlainDate, Temporal.PlainYearMonth, Temporal.PlainMonthDay, Temporal.PlainTime. Từ "Plain" tạo nên đặc trưng cho loại giờ này, nó được hiểu như là ngày giờ không quan tâm đến múi giờ.
// 2. Lấy giờ địa phương
// - Lấy ngày và giờ
const plainDateTime = Temporal.PlainDateTime.from('2025-01-01T12:34');

// - Chỉ lấy ngày
const plainDate = Temporal.PlainDate.from('2025-01-01');

// - Chỉ lấy năm và tháng, từ đó xem bao nhiêu ngày trong tháng đó hoặc trong năm đó
const plainYearMonth = Temporal.PlainYearMonth.from('2025-01');
plainYearMonth.daysInMonth; // => 31
plainYearMonth.daysInYear; // => 365

// - Chỉ lấy tháng và ngày, từ đó có thể set vào một năm nào đó và xem ngày đó là thứ mấy
const plainMonthDay = Temporal.PlainMonthDay.from('01-01'); // tạo 1 pattern ngày 01/01
const date = plainMonthDay.toPlainDate({ year: 2025 }); // => 2025-01-01
// và thêm vào pattern của năm nào đó, cụ thể 2025
date.dayOfWeek; // => 7
// xem ngày hôm đó là thứ mấy

// Chỉ lấy giờ
const plainTime = Temporal.PlainTime.from('12:34'); // => 12:34
  • Now (thời gian hiện tại): thông qua class Temporal.Now, nó giúp ta lấy giờ hiện tại (chắc chắn rồi!) và có thể chuyển thành bất cứ dạng giờ nào như đã đề cập ở trên.
// 3. Lấy giờ hiện tại
// - Lấy theo múi giờ Saigon
const dateTimeInSaiGon = Temporal.Now.zonedDateTimeISO('Asia/Saigon');
// => 2025-03-08T08:12:02.743639959+07:00[Asia/Saigon]

// - Hoặc chỉ lấy ngày
const date = Temporal.Now.plainDateISO();
// => 2025-03-08
  • Duration (khoảng thời gian): thông qua class Temporal.Duration để tạo khoảng thời gian giữa 2 thời điểm
// 4. Lấy khoảng thời gian
const duration = Temporal.Duration.from({ hours: 130, minutes: 20 }); duration.total({ unit: 'second' });
// => 469200

Như vậy, với cách chia này, Temporal sẽ giúp ta hình dung được cách xử lý ngày giờ một cách rõ ràng và chính xác hơn.

Upload image

Minh hoạ về các loại định dạng ngày giờ. Nguồn: Proposal Temporal

Các tính năng nổi bật

Để có cái nhìn tổng quan nhất, ta hãy xem cách mà Temporal API đã giải quyết những hạn chế của Date cũng như so sánh với thư viện phổ biến Moment.js.

Hỗ trợ sẵn múi giờ

Temporal đã tích hợp sẵn ngay từ đầu với Temporal.ZonedDateTime mà không cần cài bất cứ thứ gì, còn với Moment.js bạn phải cần thêm plugin moment-timezone để có thể xử lý múi giờ.

Ví dụ, lấy múi giờ ở New York:

// Với Moment - cài thêm "moment-timezone"
const moment = require("moment-timezone"); 
const nowInNY = moment().tz("America/New_York").format(); 
console.log(nowInNY);
// "2025-03-08T10:30:00-05:00"


// Với Temporal
const nowInNY = Temporal.Now.zonedDateTimeISO("America/New_York"); console.log(nowInNY.toString()); 
// "2025-03-08T10:30:00.123456789-05:00[America/New_York]"

Tính bất biến

Mọi thứ trong Temporal đều là bất biến, mỗi thao tác đều tạo ra một instance mới và chúng sẽ không vô tình 'đụng chạm' gì đến nhau.

Ví dụ:

// Với Date - mutable
const date = new Date(2025, 03, 08); 
date.setFullYear(2026); 
console.log(date); // Đổi thành "2026-03-08"

// Với Temporal
const date = Temporal.PlainDate.from({ year: 2025, month: 3, day: 8 }); 
const newDate = date.with({ year: 2026 }); 
console.log(date.toString()); // "2025-03-08" (Không bị đổi)
console.log(newDate.toString()); // "2026-03-08"

Đa dạng về lịch

Ngoài lịch dương Gregorian, Temporal còn hỗ trợ với nhiều loại lịch khác như lịch âm (Chinese), Do Thái (Hebrew), Hồi giáo (Islamic). Điều này cực kỳ hữu ích cho ứng dụng đa văn hóa. Giờ đây việc xem lịch âm của một ngày cụ thể nào đó dễ hơn bao giờ hết.

Ví dụ, xem tết năm 2026 sẽ bắt đầu từ ngày nào - chỉ với một hàm duy nhất!

Temporal.PlainDate.from({
  monthCode: "M01",
  day: 1,
  year: 2026,
  calendar: "chinese",
}).withCalendar('iso8601').toLocaleString()

// "2/17/2026"

Độ chính xác cao

Trong khi Date hay Moment.js chỉ hỗ trợ trả kết quả ngày giờ đến milliseconds, Temporal trả kết quả tới nanoseconds, điều cần thiết cho các ứng dụng tài chính, khoa học hay IoT cần độ chi tiết cao.

const now = Temporal.Now.instant(); 
console.log(now.toString());

// "2025-03-08T10:00:00.123456789Z"

Native siêu nhẹ, hiệu suất cao

Vấn đề lớn của Moment.js đó là kích thước bundle lớn (~70KB) làm tăng thời gian tải trang, ảnh hưởng đến hiệu suất của ứng dụng. Ngược lại, vì là một API native, Temporal được tích hợp sẵn vào JavaScript, có thể sử dụng ngay lập tức mà không cần phải qua bước cài đặt nào giúp cải thiện hiệu suất đáng kể.

Điểm hạn chế

Dù có phần vượt trội hơn so với các thư viện bên ngoài, cụ thể là Moment.js, tuy nhiên vì 'sinh sau đẻ muộn' nên Temporal cũng chưa hoàn toàn đầy đủ về mặt tính năng như Moment.js, có thể kể đến như:

  • Việc parsing chưa được linh hoạt: Temporal không có khả năng parse nhiều định dạng phức tạp như Moment.js, ta cần phải dùng đến một thư viện khác nhẹ hơn là date-fns để parse trước rồi chuyển sang Temporal.
  • Định dạng ngày giờ bị hạn chế: Temporal có phần lép vế hơn trong việc định dạng ngày giờ. Để đảm bảo được tính năng này gần giống với Moment.js, hãy kết hợp nó với Intl.DateTimeFormat từ API native Intl.

Kết luận

Có thể nói, Temporal là tương lai của JavaScript, từ việc định nghĩa lại các khái niệm về thời gian đến việc xử lý thời gian chính xác, đơn giản và chuẩn chỉnh hơn bao giờ hết. Dù vẫn còn một số điểm chưa hoàn thiện nhưng tiềm năng của Temporal là không thể phủ nhận và nó hoàn toàn có thể trở thành 'trợ thủ' đắc lực cho các lập trình viên. Vì Temporal cũng đang phát triển dần cho giai đoạn chính thức và bạn sẽ không biết nó sẽ tốt hơn như thế nào trong tương lai, cùng chờ đoán nhé.

Tham khảo

JavaScript Temporal is coming

Proposal Temporal

Atekco - Home for Authentic Technical Consultants