)
date-fns 生态 date-fns/utc 完整演进史从 UTCDate 时区缺陷修复到 ESM-first 与 tz 上下文v1.0.0 → v2.1.1【免费下载链接】date-fns⏳ Modern JavaScript date utility library ⌛️项目地址: https://gitcode.com/gh_mirrors/da/date-fnsdate-fns/utc是 date-fns 生态中专为「UTC 计算」设计的官方配套包提供UTCDate与UTCDateMini两个 Date 扩展类让所有日期计算固定发生在 UTC 而非系统时区。本文以该包在 pkgs/utc/CHANGELOG.md 中记录的完整版本历史为主线结合 pkgs/utc/src 下的真实源码与测试梳理从 2022 年 v1.0.0 首发到 2025 年 v2.1.1 期间的关键演进、破坏性变更与升级迁移要点。读完本文你将清楚掌握该包的 API 全貌、体积权衡UTCDateMini仅 239 B、ESM-first 迁移注意事项以及如何在 date-fns v4 中通过utc/tz上下文函数彻底规避 DST 与时区偏差问题。一、版本演进总览date-fns/utc采用 Semantic Versioning 语义化版本规范变更日志遵循 Keep a CHANGELOG 格式全部记录在仓库 pkgs/utc/CHANGELOG.md 中。完整版本时间线如下版本发布日期类型核心变更v1.0.02022-07-10首发初始版本v1.1.02023-04-10特性新增字符串解析支持v1.1.12023-12-22修复更新exports字段兼容更多环境v1.2.02024-03-09特性支持 Sinon fake timers 及覆盖Date.now/Date构造器的测试库v2.0.02024-09-10破坏性转为 ESM-first新增utc上下文函数补充LICENSE.mdv2.0.12024-09-11修复修复UTCDateMini类型定义v2.1.02024-09-14特性扩充 README 与 JSDoc 文档v2.1.12025-07-30修复调整package.json的main字段以修复 CommonJS 支持可以看到这个包从最初发布到成熟稳定跨越了约三年其演进主线可以归纳为三个方向① 环境兼容性加固CJS/ESM 双形态、fake timers、② 类型与文档完善、③ 与 date-fns v4 的in上下文选项深度集成。二、v1.0.0核心能力奠基2022-07-10初始版本确立了包的两个核心导出类UTCDate与UTCDateMini。从 pkgs/utc/src/index.ts 可以看到包对外统一导出了date与utc两大部分export * from ./date/index.js; export * from ./date/mini.js; export * from ./utc/index.ts;2.1 设计原理getter/setter 的 UTC 映射UTCDateMini的核心实现位于 pkgs/utc/src/date/mini.js。其精妙之处在于一个正则会替换逻辑// Replace getter and setter functions with UTC counterparts const re /^(get|set)(?!UTC)/; Object.getOwnPropertyNames(Date.prototype).forEach((method) { if (re.test(method)) { const utcMethod Date.prototype[method.replace(re, $1UTC)]; if (utcMethod) UTCDateMini.prototype[method] utcMethod; } });这段代码遍历Date.prototype上所有以get/set开头但不以UTC开头的方法将它们逐一替换为对应的 UTC 版本。例如getHours→getUTCHours、setDate→setUTCDate从而让所有基于这些 getter/setter 的日期运算天然发生在 UTC 时区。同时通过覆写getTimezoneOffset()恒返回0彻底抹除系统时区偏移getTimezoneOffset() { return 0; }2.2 构造器对多形态输入的处理构造器pkgs/utc/src/date/mini.js支持无参、时间戳、字符串和多个日期分量四种形态this.setTime( arguments.length 0 ? Date.now() // 当前时刻 : arguments.length 1 ? typeof arguments[0] string ? new Date(arguments[0]) // 字符串解析 : arguments[0] // 时间戳或 Date 实例 : Date.UTC(...arguments), // 分量形式始终按 UTC 解释 );多分量构造如new UTCDate(2022, 2, 13)直接走Date.UTC(...)这正是与原生new Date(2022, 2, 13)行为差异的根源——后者按系统时区解释年月日前者按 UTC 解释。相关行为在 pkgs/utc/src/date/tests.ts 中有完整测试覆盖例如it(creates date in UTC, () { const tzOffset -new Date(1987, 1, 11).getTimezoneOffset(); const hoursOffset Math.trunc(tzOffset / 60); const minutesOffset tzOffset % 60; expect(new UTCDate(1987, 1, 11).getTime()).toBe( new Date(1987, 1, 11, hoursOffset, minutesOffset).getTime(), ); });该测试用系统时区偏移反推原生Date的等价时间戳验证UTCDate构造的结果确实等于「原生 Date 在 UTC 下解释分量」的时间点。2.3 完整版与迷你版的分工UTCDate继承自UTCDateMini见 pkgs/utc/src/date/index.js在其基础上补齐了格式化函数能力UTCDateMiniUTCDategetter/setterUTC 映射✅✅getTimezoneOffset()返回 0✅✅toString()/toDateString()/toTimeString()❌✅toLocaleString/toLocaleDateString/toLocaleTimeString❌✅构建体积239 B504 BUTCDate的格式化实现依赖Intl.DateTimeFormat并显式传入timeZone: UTC见 pkgs/utc/src/date/index.jsvar weekdayFormat new Intl.DateTimeFormat(en-US, { weekday: short, timeZone: UTC, });其toLocaleString系列则在调用原生方法时强制注入timeZone: UTC且允许用户通过 options 覆盖测试 pkgs/utc/src/date/tests.ts 验证了传timeZone: Asia/Kolkata可切换为其他时区。三、v1.1.0字符串解析支持2023-04-10v1.1.0 为UTCDate/UTCDateMini增加了字符串构造支持。构造器中对单参数且类型为字符串的分支执行new Date(arguments[0])即复用原生Date的字符串解析语义来得到时间戳。测试中对应验证为it(allows to parse the string, () { expect(new UTCDate(2023-05-03)).toBe(new Date(2023-05-03)); });这意味着new UTCDate(2023-05-03)与new Date(2023-05-03)解析到同一时间点但后续所有 getter/setter 都按 UTC 语义工作。注意ISO 8601 字符串如2023-05-03按规范本就按 UTC 解释无时区后缀视为 Z而带偏移的字符串如2024-09-09T23:00:00-04:00则会被精确换算为绝对时间点。四、v1.1.1exports 环境兼容性加固2023-12-22v1.1.1 通过更新package.json的exports字段让包兼容更多运行环境。从当前仓库 pkgs/utc/package.json 可以看到完整的导出映射包含requireCJS与importESM双通道并为每条通道分别提供.d.cts/.d.ts类型声明exports: { .: { require: { types: ./index.d.cts, default: ./index.cjs }, import: { types: ./index.d.ts, default: ./index.js } }, ./date: { ... }, ./date/mini: { ... }, ./utc: { ... } }同时支持子路径导入date-fns/utc主入口、date-fns/utc/date、date-fns/utc/date/mini、date-fns/utc/utc方便按需引入以进一步控制构建体积。五、v1.2.0fake timers 与测试生态适配2024-03-09v1.2.0 增加了对 Sinon fake timers、Jest 等依赖它的框架以及其他覆写Date.now和Date构造器的测试库的支持。关键实现在构造器的无参分支中pkgs/utc/src/date/mini.jsarguments.length 0 ? // Enables Vitest/Sinon fake timers that override the constructor Date.now() : ...代码注释明确说明了设计意图通过调用Date.now()而非缓存系统时间来创建「当前时刻」从而让 Sinon/Vitest 等 fake timers 能够无缝接管。对应测试位于 pkgs/utc/src/date/tests.tsit(mocks the date, () { const expected new Date(1987, 1, 11, 12, 13, 14, 15); expect(new Date()).toBe(expected); expect(new UTCDate()).toBe(expected); });测试通过vi.useFakeTimers({ now: new Date(1987, 1, 11, 12, 13, 14, 15) })模拟固定时间并断言new UTCDate()与new Date()返回相同的时间戳。这意味着在测试中冻结时间时UTCDate相关逻辑也能保持确定性。六、v2.0.0破坏性变更与上下文函数2024-09-10v2.0.0 是包历史上最重要的一次大版本升级包含三项变更其中两项具有破坏性影响。6.1 ⚠️ BREAKINGESM-first从 v2.0.0 起包转为ESM-first策略。虽然 CommonJS 仍受支持但在某些环境中可能触发问题官方在变更日志中明确呼吁遇到问题请到 issue 跟踪 反馈。当前 pkgs/utc/package.json 中type: module与双通道exports并存正是这一策略的体现ESM 导入走./index.jsCJSrequire走./index.cjs。而在后续 v2.1.1 中进一步修正了main字段以保证 CJS 场景可用详见第八节。迁移建议升级到 v2.x 后优先确认你的打包工具/运行时对exports条件导出的支持情况若在 Node 老版本或特殊打包环境下出现模块解析问题可通过检查main、module、exports三者的一致性来排查。6.2 新增utc上下文函数date-fns ≥ v4v2.0.0 新增了utc函数用于为 date-fns v4 的函数通过in选项指定计算上下文。其实现位于 pkgs/utc/src/utc/index.tsexport const utc (value: Date | number | string) new UTCDate(new Date(value));utc接受日期值、时间戳或字符串统一转换为UTCDate实例返回。utc测试pkgs/utc/src/utc/tests.ts验证了三种输入形态的等价性const dateStr 2020-01-01T08:00:00.00008:00; expect(utc(dateStr).toISOString()).toBe(2020-01-01T00:00:00.000Z); expect(utc(new Date(dateStr)).toISOString()).toBe(2020-01-01T00:00:00.000Z); expect(utc(new Date(dateStr)).toISOString()).toBe(2020-01-01T00:00:00.000Z);即无论传入带偏移字符串、时间戳还是Date实例utc()都得到同一 UTC 时间点东八区的 08:00 精确换算为 00:00 UTC。与tz的对应关系变更日志中同步提到tz函数来自date-fns/tz包允许指定时区上下文二者在 date-fns v4 中配合使用import { isSameDay } from date-fns; import { tz } from date-fns/utc; isSameDay(2024-09-09T23:00:00-04:00, 2024-09-10T10:00:0008:00, { in: tz(America/New_York), }); // true而纯 UTC 场景则直接使用utcimport { isSameDay } from date-fns; import { utc } from date-fns/utc; isSameDay(2024-09-09T23:00:00-04:00, 2024-09-10T10:00:0008:00, { in: utc, }); // true两个在不同时区标记的时间点在指定 UTC/纽约时区上下文中被判定为同一天——这正是上下文选项解决跨时区日期比较问题的核心价值。仓库中对应的完整示例可参考 pkgs/utc/examples 下的 cjs/esm/cts/ts 四套示例工程。6.3 补充 LICENSE.mdv2.0.0 将 MIT 许可证以显式LICENSE.md文件形式随包分发此前仅存在于项目层面。注意这仅是将许可证声明显式化许可协议本身一直是 MIT不构成行为变更。七、v2.0.1UTCDateMini 类型修复2024-09-11v2.0.1 修复了UTCDateMini的类型定义由 fabon-f1 贡献。修复前类型声明可能不完整或与运行时行为不一致修复后pkgs/utc/src/date/index.d.ts 中的UTCDate声明明确为export class UTCDate extends Date { getTimezoneOffset(): 0; }类型层面的核心契约是UTCDate/UTCDateMini与原生DateAPI 完全兼容继承Date的全部成员唯一类型层面的差异是getTimezoneOffset()被收窄为字面量类型0——这与运行时恒返回 0 的实现严格一致让 TypeScript 使用者获得更精确的类型提示。八、v2.1.x文档与打包收尾2024-09-14 → 2025-07-30v2.1.02024-09-14扩充 pkgs/utc/README.md 文档与源码 JSDoc 注释包括完整的安装、UTCDate/UTCDateMini差异对比、utc上下文函数示例、API 索引与许可证信息。源码中的类级 JSDoc如 pkgs/utc/src/date/index.d.ts也同步完善。v2.1.12025-07-30调整package.json的main字段以修复 CommonJS 支持。这是对 v2.0.0 ESM-first 迁移的补充修正——确保在仅读取main字段的老式解析环境中CJS 用户依然能正确加载模块。结合 pkgs/utc/package.json 可见main: index.cjs与module: index.js的分工配置。九、升级与迁移实战指南9.1 安装npm install date-fns/utc --save9.2 从 v1.x 升级到 v2.x 的检查清单确认 date-fns 主版本utc/tz上下文函数需要date-fns ≥ v4in选项是 v4 引入的 API。若仍在使用 date-fns v3只能使用UTCDate/UTCDateMini类而无法使用上下文函数。确认模块解析环境ESM-first 意味着需验证打包器Vite/Webpack/Rollup或运行时Node ≥ 12.17 或 14对条件导出exports的支持遇到 CJS 解析异常时检查main/exports.require路径是否正确指向index.cjs。测试环境适配v1.2.0 起已支持 fake timers若在 Jest/Sinon/Vitest 中冻结时间new UTCDate()会与new Date()同步。类型检查升级到 v2.0.1 可获得getTimezoneOffset(): 0的精确类型若你的代码对UTCDateMini做了类型断言注意与UTCDate的类型差异。9.3 典型应用场景与选型图表/日历组件渲染抽象日期时间使用UTCDateMini239 B即可因为渲染只依赖 getter/setter且体积最小需要输出格式化字符串调试或日志使用UTCDate504 B它提供了完整的toString()等格式化 API作为库对外暴露日期对象使用UTCDate更安全因为使用方可能直接调用格式化方法date-fns v4 函数需要 UTC 上下文使用utc函数或{ in: utc }选项。9.4 验证安装是否正常在任意 Node 环境TZ 环境变量可任意设置如TZAsia/Kolkata仓库测试即如此运行见 pkgs/utc/package.json 的test脚本执行import { UTCDate, UTCDateMini, utc } from date-fns/utc; new UTCDateMini(2022, 2, 13).getTimezoneOffset(); // 0 new UTCDate(2022, 2, 13).toString(); // 无论系统时区如何始终输出 Sun Mar 13 2022 00:00:00 GMT0000 (Coordinated Universal Time) utc(2020-01-01T08:00:00.00008:00).toISOString(); // 2020-01-01T00:00:00.000Z十、结论date-fns/utc的版本历史清晰地展现了它从一个「UTC Date 类」向「date-fns v4 时区上下文基础设施」演进的轨迹v1.x 打磨核心类与环境兼容性v2.0 完成 ESM-first 转型并引入utc上下文函数v2.1.x 收尾类型、文档与 CJS 兼容性。对于需要在图表、日历等场景中执行「抽象日期时间计算」的开发者UTCDateMini是最小体积239 B的优选对于需要完整 Date API 或对外暴露日期的场景UTCDate504 B更为稳妥而在 date-fns v4 中处理跨时区比较则应优先使用utc上下文函数。升级到 v2.x 时请重点核对 date-fns 版本、模块解析环境与 fake timers 配置三项即可平滑完成迁移。【免费下载链接】date-fns⏳ Modern JavaScript date utility library ⌛️项目地址: https://gitcode.com/gh_mirrors/da/date-fns创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考