ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

深入理解 JavaScript Temporal API:告别 Date 对象的现代日期时间方案

深入理解 JavaScript Temporal API:告别 Date 对象的现代日期时间方案 深入理解 JavaScript Temporal API告别 Date 对象的现代日期时间方案【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine导读JavaScript 的Date对象因糟糕的解析、可变的 API 和脆弱的时区处理长期困扰着开发者。Temporal API 是 TC39 提案中用于替代Date的新一代日期时间标准本文以 refine 仓库中的技术文档为主体结合仓库内真实使用该 API 的示例项目系统讲解 Temporal API 的核心数据类型、实战用法、高级特性与浏览器支持现状帮助你掌握一套不可变、强时区感知、严格 ISO 8601 解析的现代日期时间编程方式。什么是 Temporal APIDate对象是 JavaScript 中公认的痛点。它的实现直接借鉴自 JavaJava 早已弃用并替换了这套设计却因为向后兼容性而一直留在 JavaScript 中长期未做更新。这也是moment.js、date-fns等第三方库大量存在的原因——开发者不得不借助它们来弥补Date的缺陷。Temporal API 正是为此而生的替代方案。它由 TC39 推进在当前仓库写作本文时仍处于Stage 3提案阶段距离正式定稿很接近但尚未进入官方 ECMAScript 标准。Temporal 提供了标准的日期时间数据类型与方法核心设计思想是将日期时间对象划分为“纯plain”和“带时区zoned”两大类PlainDate、PlainTime、PlainDateTime不与任何时区关联的纯日期 / 纯时间 / 日期时间对象ZonedDateTime、Instant与特定时区关联的精确时间对象。Temporal 通过以下特性解决Date的长期问题对所有时区的一等公民支持first-class support提供固定日期和时间的不可变对象通过严格的 ISO 8601 字符串解析保证可靠性支持非公历non-Gregorian日历系统通过简单易用的 API完成日期时间计算。为什么选择 Temporal API使用 Temporal 的好处开箱即用的全时区支持不再需要date-fns或Moment.js等额外库来修正时区处理不可变性所有运算都返回新对象而不是修改原对象代码行为更可预测、更不易出错可靠的字符串解析严格遵循 ISO 8601 格式规避Date对象解析时的种种陷阱非公历日历支持可以处理其他文化背景下的日期格式简洁直观的日期计算 API加减日期、计算时长都一目了然。何时使用 Temporal API跨时区应用需要处理多个时区、复杂时区转换的全球性应用精确可靠的日期时间计算不可变语义避免运算副作用引发的 bug多日历系统场景需要呈现或处理不同文化背景日期的业务。简而言之Temporal 提供了比旧Date对象更现代、更健壮的日期时间处理方案其严格的 ISO 8601 解析能力从根本上提升了可靠性。项目环境搭建创建一个用于实验 Temporal API 的最小项目mkdir temporal-api cd temporal-api初始化并安装官方 polyfill 包npm init npm install js-temporal/polyfill由于当前提案尚未被浏览器原生支持polyfill 是唯一能在生产环境立即体验 Temporal API 的方式。仓库中的 examples/blog-react-aria/package.json 就是一个真实案例该示例项目将js-temporal/polyfill^0.4.2作为运行时依赖与refinedev/core等 refine 包并列安装说明在 refine 技术栈React 应用中引入 Temporal polyfill 是完全可行的其引入方式与普通 npm 依赖一致。创建index.html并引入模块脚本!DOCTYPE html html langen head meta charsetUTF-8 / meta http-equivX-UA-Compatible contentieedge / meta nameviewport contentwidthdevice-width, initial-scale1.0 / titleTemporal API/title script srctemporal.js typemodule/script /head body/body /html在temporal.js中导入 polyfillimport { Temporal } from js-temporal/polyfill;随后即可在浏览器控制台中逐一验证下面所有示例的输出。Temporal API 核心数据类型Temporal.Now获取当前日期时间Temporal.Now提供一系列方法获取当前时刻的各种表示。获取当前纯日期时间精确到微秒、纳秒级别const now Temporal.Now.plainDateTimeISO(); console.log(now.toString()); // 2022-08-15T17:26:43.63340363这种纳秒级精度是普通Date对象无法提供的。分别获取日期与时间const nowDate Temporal.Now.plainDateISO(); const nowTime Temporal.Now.plainTimeISO(); console.log(nowDate.toString()); // 2022-08-15 console.log(nowTime.toString()); // 17:27:51.688660566日期算术——这是旧Date对象最痛苦的操作之一在 Temporal 中却非常简单。以下代码同时增加 1 年、1 月、1 天const now Temporal.Now.plainDateISO(); console.log(now.add({ days: 1, months: 1, years: 1 }).toString()); // 2023-09-16减法同样直观const now Temporal.Now.plainDateISO(); console.log(now.subtract({ days: 1, months: 1, years: 1 }).toString()); // 2021-07-14注意add/subtract均返回新对象不会修改原日期。这正是 Temporal 与旧Date的关键差异——Date的setMonth等方法会就地修改原对象容易引发难以排查的副作用。比较两个日期const now Temporal.Now.plainDateISO(); const now2 Temporal.Now.plainDateISO(); console.log(now.equals(now2)); // true计算两个日期之间的时长since与until两个辅助方法方向相反分别计算“从给定日期到现在”和“从现在到给定日期”的时长const now Temporal.Now.plainDateISO(); const now2 new Temporal.PlainDate(2022, 1, 1); console.log(now.since(now2).toString()); // P226D console.log(now.until(now2).toString()); // -P226D输出采用 ISO 8601 时长格式P226D表示 226 天-P226D表示方向相反。with方法局部覆盖字段只修改年其余字段保持不变const now Temporal.Now.plainDateISO(); console.log(now.with({ year: 2021 }).toString()); // 2021-08-15获取带时区的当前时间zonedDateTimeISO()在字符串末尾标注时区标识const now Temporal.Now.zonedDateTimeISO(); console.log(now.toString()); // 2022-08-15T17:37:00.98602098405:00[Asia/Karachi]末尾的05:00[Asia/Karachi]同时给出 UTC 偏移量与 IANA 时区名。这种时区感知能力在普通Date对象上几乎无法轻易实现——时区与非时区之间的转换过去一直是难点。因此Temporal.Now提供了获取任意形态当前日期时间的完整方法集。Temporal.PlainDate不含时间的纯日期通过构造器创建纯日期const now new Temporal.PlainDate(2022, 8, 8); console.log(now.toString()); // 2022-08-08通过from静态方法从 ISO 字符串解析const now Temporal.PlainDate.from(2022-08-08); console.log(now.toString()); // 2022-08-08from也接受对象字面量结果完全一致const now Temporal.PlainDate.from({ year: 2022, month: 8, day: 8, }); console.log(now.toString()); // 2022-08-08from是 Temporal 中最常用的工厂方法之一它统一了“字符串 / 对象 / 其他 Temporal 对象”到目标类型的转换入口并严格执行 ISO 8601 校验——这是Date对象new Date(2022-08-08)那种宽松、易出错的解析方式无法比拟的。同理可以构造带时区的日期时间只需在对象中提供timeZone字段const now Temporal.ZonedDateTime.from({ year: 2022, month: 8, day: 8, timeZone: Temporal.Now.timeZone(), }); console.log(now.toString()); // 2022-08-08T00:00:0005:00[Asia/Karachi]由于显式指定了时区输出会包含你所在时区的偏移量信息。排序日期Temporal.PlainDate.compare作为静态比较函数可直接用于Array.prototype.sortconst today Temporal.Now.plainDateISO(); const yesterday today.subtract({ days: 1 }); const tomorrow today.add({ days: 1 }); const days [today, yesterday, tomorrow]; const sortedDays days.sort(Temporal.PlainDate.compare); console.log(sortedDays.map((d) d.toString())); // [2022-08-14, 2022-08-15, 2022-08-16]Temporal.Duration时长类型Duration表示一段时间的长度用于日期之间的比较与运算。可以通过构造器或from方法创建const duration Temporal.Duration.from({ days: 2, months: 8 }); console.log(duration.toString()); // P8M2D输出同样是 ISO 8601 时长格式P8M2D表示 8 个月零 2 天。Duration支持round、with、subtract、add等辅助方法其中total方法将整个时长换算为指定单位的总量const duration Temporal.Duration.from({ hours: 12, minutes: 30 }); console.log(duration.total(minutes)); // 75012 小时 30 分钟换算为分钟即 750这一能力在工时统计、计费等业务中非常实用。Temporal.TimeZone时区对象TimeZone类型用来表示具体时区支持从 IANA 时区名或当前环境获取const timeZone Temporal.TimeZone.from(America/Chicago); console.log(timeZone.toString()); // America/Chicago const localTimeZone Temporal.Now.timeZone(); console.log(localTimeZone.toString()); // Asia/KarachiTemporal.Now.timeZone()返回当前运行环境的时区可用于构造ZonedDateTime如前面示例所示或进行时区间的换算。Temporal API 高级特性非公历日历支持Temporal 内置多种日历系统如伊斯兰历、希伯来历等可以轻松在不同文化日期格式间切换无需额外处理Temporal.Instant精确时间戳支持纳秒级精度适合日志记录、实时数据处理等高精度场景其语义等价于 Unix 时间戳的不可变版本Temporal.Calendar自定义日历允许开发者定义符合特定业务规则的日历系统用于跟踪独特的日期体系Temporal.ZonedDateTime强时区处理可在不同时区间轻松转换日期时间是全球化应用的基石丰富的辅助方法with、add、subtract、since、until等使日期算术简单可靠且全部返回新对象保证不可变语义、杜绝意外副作用。这些特性共同构成了 Temporal 相比Date对象在灵活性、精确性与安全性上的全面优势。浏览器支持现状与 polyfill 策略截至本文档更新2024 年 6 月Temporal API 提案仍处于Stage 3各主流浏览器尚未原生实现。想要立即体验必须借助 polyfill官方 polyfilljs-temporal/polyfillnpm 包安装后即可在任意支持现代 JavaScript 的浏览器环境中使用全部 Temporal 能力仓库中的 examples/blog-react-aria/package.json 即采用此方案将js-temporal/polyfill: ^0.4.2声明为依赖后即可在 React 组件与工具函数中直接import { Temporal } from js-temporal/polyfill。在实际工程中建议将该 polyfill 作为常规运行时依赖引入并在业务代码中通过统一的工具模块封装 Temporal 的常用操作这样未来浏览器原生支持后只需移除 polyfill 依赖即可平滑迁移。结语JavaScript 的Date对象存在一系列根深蒂固的实现问题。Temporal API 用一套不可变、时区完备、解析严格且 API 友好的数据模型从根本上解决了这些痛点。无论是跨时区的全球化应用、需要高精度时间戳的日志系统还是涉及多日历的业务场景Temporal 都提供了远超旧Date的现代方案。虽然它目前仍需借助 polyfill 使用但作为 Stage 3 提案它离成为 ECMAScript 官方标准已经不远提前掌握这一 API 将让开发者获得显著的前瞻优势。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表