Temporal API 详解:JavaScript 日期处理的未来
Date 对象的世纪之痛(月份从 0 开始、可变对象、时区混乱)终于有解。Temporal API 提供不可变、时区精确的新日期体系,本文完整讲解。
Temporal 是 Date 的正式替代提案:Temporal.Now.instant() 取时刻、Temporal.PlainDate 管纯日期、ZonedDateTime 精确处理时区——全部不可变、月份从 1 开始、时区一等公民。生产使用搭配 @js-temporal/polyfill。
Date 的原罪
月份 0 起算(new Date(2026, 9, 8) 是 10 月?)、可变对象(date.setDate() 原地修改)、时区处理靠猜(本地时间与 UTC 纠缠)——三十年的坑。
Temporal 的类型体系
精确的概念分离是核心设计:
Instant:时间轴上的一个点(时间戳);PlainDate:日历日期(2026-10-08,无时区);PlainTime:一天中的时间;PlainDateTime:日期+时间(无时区);ZonedDateTime:带时区的完整时刻(纽约的 2026-10-08 14:30);Duration:时长。
"会议在下周一下午 2 点"是 PlainDateTime,"火箭发射时刻"是 Instant——概念用错类型就是 Date 时代 bug 的来源。
实战用法
// 当前时间
const now = Temporal.Now.zonedDateTimeISO('Asia/Shanghai');
// 日期运算:不可变,返回新对象
const nextWeek = now.add({ days: 7 });
const meeting = Temporal.PlainDateTime.from('2026-10-12T14:30');
const reminder = meeting.subtract({ hours: 2 });
// 时长
const duration = Temporal.Duration.from({ days: 3, hours: 5 });
// 比较
Temporal.PlainDate.compare(a, b); // -1/0/1
// 舍入
now.round({ smallestUnit: 'minute', roundingMode: 'floor' });
时区正确姿势
// 同一时刻在不同时区
const instant = Temporal.Now.instant();
instant.toString(); // UTC 时刻
const shanghai = instant.toZonedDateTimeISO('Asia/Shanghai');
const newYork = instant.toZonedDateTimeISO('America/New_York');
// 同一物理时刻,各自正确的本地表示
夏令时切换、跨时区调度——Temporal 的时区处理基于 IANA 数据库,精确性碾压 Date 的本地时区猜测。
现状与使用
提案 Stage 3+,浏览器陆续实现中。生产使用:
npm install @js-temporal/polyfill
API 形状已稳定——学它是对未来的稳赚投资(参见本系列《Moment.js 替代方案盘点》)。
常见问题(FAQ)
Q:现在生产能用吗?
polyfill 可用且被广泛使用;关注各浏览器原生实现进度,polyfill 是按最终 API 写的——未来移除 polyfill 即完成迁移。
Q:和 date-fns/Luxon 的关系?
库是对 Date 的补丁,Temporal 是替代品。长期看库会逐渐包装/迁移到 Temporal 内核。
Q:月份真的从 1 开始了?
真的:Temporal.PlainDate.from('2026-10-08').month === 10。仅此一项就值回票价。
参考文档
本文依据公开文档整理,示例需按项目依赖版本验证;不将文档中的性能描述视为本项目实测结果。