Tiếng Việt

Hướng dẫn chuyên sâu về Temporal API của JavaScript, một giải pháp hiện đại để xử lý ngày giờ hiệu quả trong các bối cảnh quốc tế đa dạng.

Temporal API của JavaScript: Xử lý Ngày và Giờ Hiện đại cho Đối tượng Toàn cầu

Đối tượng `Date` của JavaScript từ lâu đã là nguồn cơn gây khó chịu cho các nhà phát triển. Tính khả biến, API không nhất quán và hỗ trợ múi giờ kém đã dẫn đến sự ra đời của nhiều thư viện như Moment.js và date-fns để lấp đầy những khoảng trống. Giờ đây, với Temporal API, JavaScript cung cấp một giải pháp tích hợp, hiện đại để xử lý ngày và giờ với sự rõ ràng và chính xác được cải thiện. Bài viết này cung cấp một cái nhìn tổng quan toàn diện về Temporal API, tập trung vào các tính năng, lợi ích và cách sử dụng trong các bối cảnh quốc tế đa dạng.

Temporal API là gì?

Temporal API là một đối tượng toàn cục mới trong JavaScript được thiết kế để giải quyết những thiếu sót của đối tượng `Date`. Nó cung cấp một API rõ ràng, bất biến để làm việc với ngày, giờ, múi giờ và các hệ thống lịch. Quan trọng hơn, nó nhằm mục đích biểu diễn các khái niệm về ngày và giờ theo cách phù hợp hơn với cách sử dụng và mong đợi trong thế giới thực, giúp việc quốc tế hóa trở nên đơn giản hơn rất nhiều.

Các tính năng chính:

Các đối tượng Temporal cơ bản

Temporal API giới thiệu một số loại đối tượng mới. Dưới đây là một số loại cốt lõi:

Làm việc với Ngày

Tạo một `Temporal.PlainDate`

Để tạo một `Temporal.PlainDate`, bạn có thể sử dụng hàm khởi tạo:

const plainDate = new Temporal.PlainDate(2024, 10, 27); // Năm, Tháng (1-12), Ngày
console.log(plainDate.toString()); // Kết quả: 2024-10-27

Bạn cũng có thể sử dụng phương thức `from`, chấp nhận một chuỗi theo định dạng ISO 8601:

const plainDateFromString = Temporal.PlainDate.from('2024-10-27');
console.log(plainDateFromString.toString()); // Kết quả: 2024-10-27

Lấy các thành phần của Ngày

Bạn có thể truy cập các thành phần ngày riêng lẻ bằng cách sử dụng các thuộc tính như `year`, `month`, và `day`:

console.log(plainDate.year); // Kết quả: 2024
console.log(plainDate.month); // Kết quả: 10
console.log(plainDate.day); // Kết quả: 27

Phép toán với Ngày

Để cộng hoặc trừ ngày, tuần, tháng, hoặc năm, hãy sử dụng các phương thức `plus` và `minus`. Các phương thức này trả về một đối tượng `Temporal.PlainDate` mới:

const nextWeek = plainDate.plus({ days: 7 });
console.log(nextWeek.toString()); // Kết quả: 2024-11-03

const lastMonth = plainDate.minus({ months: 1 });
console.log(lastMonth.toString()); // Kết quả: 2024-09-27

So sánh Ngày

Bạn có thể so sánh các ngày bằng phương thức `compare`:

const date1 = new Temporal.PlainDate(2024, 10, 27);
const date2 = new Temporal.PlainDate(2024, 11, 15);

console.log(Temporal.PlainDate.compare(date1, date2)); // Kết quả: -1 (date1 sớm hơn date2)

Làm việc với Giờ

Tạo một `Temporal.PlainTime`

Để tạo một `Temporal.PlainTime`, sử dụng hàm khởi tạo:

const plainTime = new Temporal.PlainTime(10, 30, 0); // Giờ, Phút, Giây
console.log(plainTime.toString()); // Kết quả: 10:30:00

Hoặc sử dụng phương thức `from` với một chuỗi thời gian ISO 8601:

const plainTimeFromString = Temporal.PlainTime.from('10:30:00');
console.log(plainTimeFromString.toString()); // Kết quả: 10:30:00

Lấy các thành phần của Giờ

console.log(plainTime.hour); // Kết quả: 10
console.log(plainTime.minute); // Kết quả: 30
console.log(plainTime.second); // Kết quả: 0

Phép toán với Giờ

const later = plainTime.plus({ minutes: 15 });
console.log(later.toString()); // Kết quả: 10:45:00

Làm việc với Ngày và Giờ cùng nhau

Tạo một `Temporal.PlainDateTime`

Bạn có thể tạo một `Temporal.PlainDateTime` trực tiếp hoặc bằng cách kết hợp một `Temporal.PlainDate` và một `Temporal.PlainTime`:

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
console.log(plainDateTime.toString()); // Kết quả: 2024-10-27T10:30:00

const date = new Temporal.PlainDate(2024, 10, 27);
const time = new Temporal.PlainTime(10, 30, 0);
const combinedDateTime = date.toPlainDateTime(time);
console.log(combinedDateTime.toString()); // Kết quả: 2024-10-27T10:30:00

Múi giờ

Xử lý múi giờ một cách chính xác là rất quan trọng đối với các ứng dụng làm việc với người dùng ở các địa điểm khác nhau. Temporal API cung cấp hỗ trợ múi giờ mạnh mẽ thông qua các đối tượng `Temporal.ZonedDateTime` và `Temporal.TimeZone`.

Tạo một `Temporal.ZonedDateTime`

Để tạo một `Temporal.ZonedDateTime`, bạn cần một `Temporal.PlainDateTime` và một định danh múi giờ. Các định danh múi giờ dựa trên cơ sở dữ liệu múi giờ IANA (ví dụ: `America/Los_Angeles`, `Europe/London`, `Asia/Tokyo`).

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
console.log(zonedDateTime.toString()); // Kết quả: 2024-10-27T10:30:00-07:00[America/Los_Angeles] (Độ chênh lệch sẽ phụ thuộc vào quy tắc DST)

Ngoài ra, bạn có thể tạo `Temporal.ZonedDateTime` từ một `Instant`.

const instant = Temporal.Instant.fromEpochSeconds(1666866600); // Dấu thời gian ví dụ
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO(timeZone); // Múi giờ như 'America/Los_Angeles'
console.log(zonedDateTimeFromInstant.toString());

Chuyển đổi giữa các Múi giờ

Bạn có thể chuyển đổi một `Temporal.ZonedDateTime` sang một múi giờ khác bằng phương thức `withTimeZone`:

const newTimeZone = 'Europe/London';
const zonedDateTimeInLondon = zonedDateTime.withTimeZone(newTimeZone);
console.log(zonedDateTimeInLondon.toString()); // Kết quả: 2024-10-27T18:30:00+01:00[Europe/London]

Làm việc với Độ chênh lệch Múi giờ

Phương thức `getOffsetStringFor` của đối tượng `Temporal.TimeZone` cung cấp chuỗi chênh lệch cho một `Temporal.Instant` nhất định:

const timeZoneObject = new Temporal.TimeZone(timeZone);
const offsetString = timeZoneObject.getOffsetStringFor(zonedDateTime.toInstant());
console.log(offsetString); // Kết quả: -07:00 (Tùy thuộc vào quy tắc DST)

Điều cần thiết là phải sử dụng đúng các định danh múi giờ IANA để tính toán chính xác. Các định danh này được duy trì và cập nhật thường xuyên để phản ánh những thay đổi về giờ mùa hè và ranh giới múi giờ.

Khoảng thời gian (Durations)

Đối tượng `Temporal.Duration` biểu diễn một khoảng thời gian. Nó có thể được sử dụng để cộng hoặc trừ vào ngày và giờ.

Tạo một `Temporal.Duration`

Bạn có thể tạo một `Temporal.Duration` bằng cách sử dụng hàm khởi tạo, chỉ định năm, tháng, ngày, giờ, phút, giây, mili giây, micro giây và nano giây:

const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9); // Năm, Tháng, Ngày, Giờ, Phút, Giây, Mili giây, Micro giây, Nano giây
console.log(duration.toString()); // Kết quả: P1Y2M3DT4H5M6.007008009S

Hoặc bằng cách sử dụng một chuỗi khoảng thời gian ISO 8601:

const durationFromString = Temporal.Duration.from('P1Y2M3DT4H5M6S');
console.log(durationFromString.toString()); // Kết quả: P1Y2M3DT4H5M6S

Thêm Khoảng thời gian vào Ngày và Giờ

const plainDate = new Temporal.PlainDate(2024, 10, 27);
const duration = new Temporal.Duration(0, 0, 7); // 7 ngày
const newDate = plainDate.plus(duration);
console.log(newDate.toString()); // Kết quả: 2024-11-03

Lưu ý rằng việc thêm các khoảng thời gian liên quan đến tháng hoặc năm vào ngày cần được xem xét cẩn thận, vì số ngày trong một tháng hoặc một năm có thể thay đổi.

Hệ thống Lịch

Temporal API hỗ trợ các hệ thống lịch khác ngoài lịch Gregory. Điều này rất quan trọng đối với các ứng dụng cần xử lý ngày tháng trong các bối cảnh văn hóa khác nhau. Mặc dù hỗ trợ vẫn đang phát triển, nó cung cấp một nền tảng cho việc mở rộng trong tương lai.

Sử dụng Lịch thay thế

Để sử dụng một lịch cụ thể, bạn có thể chỉ định nó khi tạo các đối tượng Temporal:

const hebrewDate = new Temporal.PlainDate(5785, 1, 1, { calendar: 'hebrew' });
console.log(hebrewDate.toString()); // Kết quả cụ thể có thể khác nhau tùy thuộc vào việc triển khai và định dạng. Yêu cầu polyfill trong nhiều môi trường tại thời điểm viết bài này.

Quan trọng: Hỗ trợ cho các lịch không phải là Gregory có thể yêu cầu polyfill hoặc hỗ trợ trình duyệt/môi trường cụ thể. Kiểm tra tài liệu Temporal API và các bảng tương thích của trình duyệt để biết thông tin mới nhất.

Định dạng Ngày và Giờ

Trong khi Temporal API tập trung vào việc thao tác ngày và giờ, việc định dạng thường được xử lý bởi đối tượng `Intl.DateTimeFormat`, một phần của Internationalization API. Các đối tượng Temporal hoạt động liền mạch với `Intl.DateTimeFormat`.

Sử dụng `Intl.DateTimeFormat`

Đây là cách định dạng một `Temporal.PlainDate` bằng `Intl.DateTimeFormat`:

const plainDate = new Temporal.PlainDate(2024, 10, 27);
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatter.format(plainDate)); // Kết quả: October 27, 2024

const formatterGerman = new Intl.DateTimeFormat('de-DE', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatterGerman.format(plainDate)); // Kết quả: 27. Oktober 2024

Bạn có thể tùy chỉnh các tùy chọn định dạng để phù hợp với nhu cầu của mình. Đối số đầu tiên của `Intl.DateTimeFormat` là ngôn ngữ (locale), quyết định ngôn ngữ và các quy ước khu vực được sử dụng để định dạng. Sử dụng các ngôn ngữ khác nhau (ví dụ: 'en-US', 'de-DE', 'fr-FR', 'ja-JP') sẽ tạo ra các định dạng đầu ra khác nhau.

Định dạng `Temporal.ZonedDateTime`

Việc định dạng `Temporal.ZonedDateTime` cũng tương tự, nhưng bạn cũng có thể bao gồm thông tin múi giờ trong kết quả:

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);

const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'short' });
console.log(formatter.format(zonedDateTime)); // Kết quả: October 27, 2024, 10:30 AM PDT (Tên viết tắt của múi giờ phụ thuộc vào quy tắc DST)

Các phương pháp hay nhất về Quốc tế hóa

Khi làm việc với ngày và giờ trong bối cảnh toàn cầu, hãy ghi nhớ các phương pháp hay nhất sau đây:

So sánh Temporal API với Đối tượng Date cũ

Dưới đây là bảng nêu bật những khác biệt chính và lợi thế của Temporal API so với đối tượng `Date` cũ:

Tính năng Đối tượng `Date` cũ Temporal API
Tính khả biến Khả biến (sửa đổi đối tượng gốc) Bất biến (trả về đối tượng mới)
Hỗ trợ Múi giờ Hạn chế và thường gặp vấn đề Mạnh mẽ và chính xác, dựa trên cơ sở dữ liệu múi giờ IANA
API Không nhất quán và khó sử dụng Rõ ràng, nhất quán và trực quan
Độ chính xác Millisecond Nanosecond
Hệ thống Lịch Giới hạn ở lịch Gregory Hỗ trợ các hệ thống lịch thay thế (với sự hỗ trợ đang phát triển)
Quốc tế hóa Yêu cầu thư viện bên ngoài để quốc tế hóa mạnh mẽ Hỗ trợ tích hợp và tích hợp liền mạch với `Intl.DateTimeFormat`

Hỗ trợ Trình duyệt và Polyfills

Là một API tương đối mới, sự hỗ trợ của trình duyệt cho Temporal API vẫn đang phát triển. Kiểm tra các bảng tương thích trình duyệt mới nhất (ví dụ: trên MDN Web Docs) để xem trình duyệt và môi trường nào hỗ trợ nó nguyên bản. Đối với các trình duyệt cũ hơn hoặc môi trường không có hỗ trợ nguyên bản, bạn có thể sử dụng polyfill để cung cấp chức năng của Temporal API. Tìm kiếm "Temporal API polyfill" trên web để tìm các tùy chọn phù hợp.

Kết luận

Temporal API của JavaScript đại diện cho một bước tiến đáng kể trong việc xử lý ngày và giờ trong JavaScript. Tính bất biến, API rõ ràng, hỗ trợ múi giờ mạnh mẽ và khả năng hệ thống lịch của nó làm cho nó trở thành một công cụ mạnh mẽ cho các nhà phát triển xây dựng các ứng dụng cần làm việc với ngày và giờ một cách chính xác và đáng tin cậy trong các bối cảnh quốc tế đa dạng. Mặc dù hỗ trợ trình duyệt vẫn đang phát triển, những lợi ích của Temporal API khiến nó đáng để học và áp dụng cho các dự án mới. Bằng cách nắm bắt Temporal API và tuân theo các phương pháp hay nhất về quốc tế hóa, bạn có thể tạo ra các ứng dụng cung cấp trải nghiệm ngày và giờ liền mạch và chính xác cho người dùng trên toàn thế giới.

Tìm hiểu thêm