微风拂过
带来远处花香与青草的气息

JavaScript 即将推出时间模块

新的 JavaScript Temporal 对象的实现开始在浏览器的实验性版本中推出。 这对网络开发者来说是个重大消息,因为在 JavaScript 中处理日期和时间将大大简化并实现现代化。

依赖于调度、国际化或对时间敏感的数据的应用程序将能够使用内置功能来高效、精确且一致地处理日期、时间、持续时间和日历。 距离实现稳定且跨浏览器的支持还有很长的路要走,而且随着实现的发展可能会有变化,但我们现在已经可以看看 Temporal 当前的情况、它令人兴奋之处以及它解决了哪些问题。

为了帮助您快速上手,本周在 MDN 上新增了超过 270 页的 Temporal 文档,其中包含详细的解释和示例。

什么是 JavaScript 时间(Temporal)

要理解 Temporal,我们可以看看 JavaScript 的 Date 对象。 1995 年 JavaScript 创立时, Date 对象是从 Java 早期有缺陷的 Date 实现复制而来的。 Java 在 1997 年就替换了这一实现,但 JavaScript 却在近 30 年的时间里一直沿用着同样的 API,尽管存在已知的问题。

JavaScript 的 Date 对象存在的主要问题在于它仅支持用户本地时间和协调世界时(UTC),并且不支持时区。此外,其解析行为非常不可靠,而且 Date 本身是可变的,这可能会引入难以追踪的错误。还有其他一些问题,比如跨越夏令时(DST)和历史历法变更的计算,这些问题一直以来都很难处理。

所有这些问题都使得在 JavaScript 中处理日期和时间变得复杂且容易出错,这可能会给某些系统带来严重后果。 大多数开发人员依靠像 Moment.js 和 date-fns 这样的专用库来更好地处理其应用程序中的日期和时间。

Temporal 被设计为 Date 对象的全面替代品,使日期和时间管理变得可靠且可预测。 Temporal 增加了对时区和日历表示的支持,提供了许多内置方法用于转换、比较、计算、格式化等操作。 其 API 接口包含超过 200 个实用方法,您可以在 MDN 上的 Temporal 文档中找到有关所有这些方法的信息。

核心概念

在 Temporal 中,关键概念是它具有瞬间(历史中的独特点)、实时时钟时间(区域时间)和持续时间。 其 API 具有这种总体结构来处理这些概念:

  • 持续时间: Temporal.Duration  两个时间点之间的差值
  • 时间点:
    • 独特的时刻:
      • 作为时间戳: Temporal.Instant
      • 带有时区的日期时间: Temporal.ZonedDateTime
    • 不考虑时区的日期/时间(“普通”):
      • 完整日期和时间:  Temporal.PlainDateTime 
        • 仅日期: Temporal.PlainDate
          • 年份和月份: Temporal.PlainYearMonth
          • 月份和日期: Temporal.PlainMonthDay
        • 正是时候: Temporal.PlainTime
  • 现在: 使用  Temporal.now  获取当前时间作为各种类的实例,或者以特定格式获取

时间的例子

Temporal 的一些最基本用法包括获取当前日期和时间的 ISO 字符串,但从下面的示例中我们可以看到,现在我们可以在许多方法中提供时区,这可以处理您可能自己进行的复杂计算:

// The current date in the system's time zone
const dateTime = Temporal.Now.plainDateTimeISO();
console.log(dateTime); // e.g.: 2025-01-22T11:46:36.144

// The current date in the "America/New_York" time zone
const dateTimeInNewYork = Temporal.Now.plainDateTimeISO("America/New_York");
console.log(dateTimeInNewYork);
// e.g.: 2025-01-22T05:47:02.555

使用不同的日历也变得简单了,因为可以创建除公历之外的其他日历系统中的日期,例如希伯来历、中国历和伊斯兰历等。 下面的代码可以帮助您找出下一个中国新年是什么时候(很快就要到了!):

// Chinese New Years are on 1/1 in the Chinese calendar
const chineseNewYear = Temporal.PlainMonthDay.from({
monthCode: "M01",
day: 1,
calendar: "chinese",
});
const currentYear = Temporal.Now.plainDateISO().withCalendar("chinese").year;
let nextCNY = chineseNewYear.toPlainDate({ year: currentYear });
// If nextCNY is before the current date, move forward by 1 year
if (Temporal.PlainDate.compare(nextCNY, Temporal.Now.plainDateISO()) <= 0) {
nextCNY = nextCNY.add({ years: 1 });
}
console.log(
`The next Chinese New Year is on ${nextCNY.withCalendar("iso8601").toLocaleString()}`,
);
// The next Chinese New Year is on 1/29/2025 (at the time of writing)

使用 Unix 时间戳是一种非常常见的用例,因为许多系统(API、数据库)都使用这种格式来表示时间。 以下示例展示了如何获取以毫秒为单位的 Unix 纪元时间戳,从中创建一个瞬间,使用 Temporal.Now 获取当前时间,然后计算从现在到该 Unix 时间戳还有多少小时:

// 1851222399924 is our timestamp
const launch = Temporal.Instant.fromEpochMilliseconds(1851222399924);
const now = Temporal.Now.instant();
const duration = now.until(launch, { smallestUnit: "hour" });
console.log(`It will be ${duration.toLocaleString("en-US")} until the launch`);
// "It will be 31,600 hr until the launch" <- @js-temporal/polyfill
// "It will be PT31600H until the launch" <- Firefox Nightly

目前,在 Firefox 实现中, toLocaleString 不会输出本地化敏感的字符串,因此超过 ( PT31600H ) 的持续时间将以非本地化敏感的持续时间格式返回。 这可能会改变,因为这更多是一个设计决策,而非技术限制,因为格式化持续时间是可行的,所以填充实现和 Firefox 实现最终可能会趋同。 有很多值得强调的地方,但在 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' ][

随着实验性实现的落地,现在是尝试 Temporal 并熟悉它将成为 JavaScript 中处理日期和时间的现代方法的好时机。

赞(0) 打赏
版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
文章名称:JavaScript 即将推出时间模块
文章链接:https://www.fec.xyz/course/2025-380.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

微信扫一扫

登录

找回密码

注册