新的 JavaScript Temporal API 已陆续在浏览器实验版本中发布,这对 Web 开发人员很利好,因为其大大简化了 JavaScript 中日期和时间的处理。

至此,依赖于调度 (Scheduling)、国际化 (Internationalization) 或时间敏感数据的应用程序将能够使用 Temporal 内置功能来获得高效、精确和一致的日期、时间和日历等数据。
虽然 Temporal API 距离稳定的跨浏览器支持还有很长的路要走,而且可能随时会发生变化,但至少前端开发者可以开始逐步了解和认识强大的 Temporal API 了。
为什么强烈需要 Temporal API1995 年 JavaScript 诞生时从有缺陷的 java.util.Date 中复制了 Date 对象。但 Java 于 1997 年重新实现了 Date,而 JavaScript 30 年来却一直沿用了该存在缺陷的 API。

JavaScript Date 对象的主要问题是仅支持用户本地时间和 UTC(Coordinated Universal Time),并且不支持时区。此外,Date 的解析行为非常不可靠且是可变的,从而导致难以追踪的错误。同时,跨夏令时 (DST) 和历史日历更改计算等问题也非常难处理。
UTC 是一种基于国际原子时(TAI,International Atomic Time)和天文观测的时间标准,其结合了原子钟的高精度和地球自转的变化以确保时间准确性和一致性。
Date 的所有这些问题都使得在 JavaScript 中使用日期和时间变得复杂且容易出错,因此诸多开发者会依靠 Moment.js 和 date-fns 等专用库来更好地处理应用程序中的日期和时间。
而 Temporal 的出现旨在完全替代 Date 对象,使日期和时间管理变得可靠且可预测,其增加了对时区和日历的支持,以及诸多用于转换、比较、计算、格式化等 200 多种内置方法。
JavaScript Temporal 的核心概念在 Temporal 中,关键概念是其具有瞬间(历史上的唯一时间点)、挂钟时间(时区时间)和持续时间 (Duration)。

API 具有以下总体结构来处理这些概念:
持续时间:Temporal.Duration 两个时间点之间的差异时间点唯一时间点作为时间戳:Temporal.Instant带有时区的日期时间:Temporal.ZonedDateTime不包含时区的日期 / 时间(Plain)完整日期和时间:Temporal.PlainDateTime仅日期:Temporal.PlainDate年和月:Temporal.PlainYearMonth月和日:Temporal.PlainMonthDay仅时间:Temporal.PlainTimenow:使用 Temporal.now 获取当前时间作为各种类实例或特定格式Temporal 示例支持获取指定时区日期Temporal 的最基本用法包括以 ISO 字符串形式获取当前日期和时间,同时还可以使用多种方法来提供时区:
// 系统时区的当前日期const dateTime = Temporal.Now.plainDateTimeISO();console.log(dateTime);// 返回值 2025-01-22T11:46:36.144// America/New_York 时区的当前日期const dateTimeInNewYork = Temporal.Now.plainDateTimeISO("America/New_York");console.log(dateTimeInNewYork);// 输出数据 2025-01-22T05:47:02.555支持其他日历系统日期除了公历之外,开发者还可以创建其他日历系统的日期对象等。下面代码获取下一个农历新年的日期:
const chineseNewYear = Temporal.PlainMonthDay.from({ monthCode: "M01", day: 1, calendar: "chinese",});// 创建中国农历新年(农历正月初一)的 Temporal.PlainMonthDay 对象const currentYear = Temporal.Now.plainDateISO().withCalendar("chinese").year;// 获取当前年份,输出 2025let nextCNY = chineseNewYear.toPlainDate({ year: currentYear });// 如果 nextCNY 在当前日期之前则移动到下一年if (Temporal.PlainDate.compare(nextCNY, Temporal.Now.plainDateISO()) <= 0) { nextCNY = nextCNY.add({ years: 1 });}console.log( ` 下一个农历新年是: ${nextCNY.withCalendar("iso8601").toLocaleString()}`);// 下一个农历新年是 2026/2/17获取时间戳下面示例获取以毫秒为单位的 Unix 纪元时间戳,使用 Temporal.Now 获取当前时间,然后计算从现在到 Unix 时间戳间隔的小时数:
const launch = Temporal.Instant.fromEpochMilliseconds(1851222399924);// 1851222399924 表示时间戳const now = Temporal.Now.instant();const duration = now.until(launch, { smallestUnit: "hour" });console.log(` 到 launch 间隔 ${duration.toLocaleString("en-US")} 小时 `);// 到 launch 间隔 31,225 hr 小时Temporal API 还提供了强大的 compare() 方法,其允许开发者对持续时间进行合理的排序:
const durations = [ Temporal.Duration.from({ hours: 1 }), Temporal.Duration.from({ hours: 2 }), Temporal.Duration.from({ hours: 1, minutes: 30 }), Temporal.Duration.from({ hours: 1, minutes: 45 }),];durations.sort(Temporal.Duration.compare);console.log(durations.map((d) => d.toString()));// 输出结果 ['PT1H', 'PT1H30M', 'PT1H45M', 'PT2H']参考资料https://developer.mozilla.org/en-US/blog/javascript-temporal-is-coming/
https://cdn.jsdelivr.net/npm/temporal-polyfill@0.2.5/global.min.js
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal
https://baike.baidu.com/item/协调世界时/787659
https://www.wearedevelopers.com/en/magazine/544/the-temporal-api-how-javascript-dates-might-actually-be-getting-fixed-544
https://dev.to/neeraj1997dev/temporal-dead-zone-tdz-in-javascript-5207