Node.js 26 Temporal API完全教程:告别Date对象的12种用法

Node.js 26正式启用了Temporal API,这是JavaScript处理日期和时间的全新标准。如果你已经受够了Date对象的坑——可变性、时区混乱、月份从0开始——这篇教程将带你从零掌握Temporal API的所有核心用法。

为什么Temporal比Date好?

先看一个经典的Date坑:

const d = new Date(2026, 0, 1);  // 注意:月份从0开始!
console.log(d.getMonth());  // 0,不是1

// Date是可变的,这会导致bug
const d1 = new Date('2026-01-01');
const d2 = d1;
d2.setMonth(5);
console.log(d1.getMonth());  // 5!d1也被改了

Temporal解决了这些问题。所有Temporal对象都是不可变的,月份从1开始,时区处理清晰明确。

核心类型一览

类型 用途 示例
PlainDate 只有日期,没有时间和时区 2026-05-20
PlainTime 只有时间,没有日期和时区 14:30:00
PlainDateTime 日期+时间,没有时区 2026-05-20T14:30:00
ZonedDateTime 日期+时间+时区(最常用) 2026-05-20T14:30:00+08:00[Asia/Shanghai]
Instant 精确到纳秒的时间点 2026-05-20T06:30:00Z
Duration 时间段 P1Y2M3DT4H5M6S

12种常见用法

1. 获取当前时间

// 当前时区的日期时间
const now = Temporal.Now.zonedDateTimeISO();
console.log(now.toString());
// 2026-05-20T14:30:00.000+08:00[Asia/Shanghai]

// 当前日期
const today = Temporal.Now.plainDateISO();
console.log(today.toString());
// 2026-05-20

// UTC时间点
const instant = Temporal.Now.instant();
console.log(instant.toString());
// 2026-05-20T06:30:00Z

2. 创建指定日期

// 创建日期对象
const date = Temporal.PlainDate.from('2026-12-25');
console.log(date.year);   // 2026
console.log(date.month);  // 12(不是0!)
console.log(date.day);    // 25

// 从对象创建
const date2 = Temporal.PlainDate.from({ year: 2026, month: 6, day: 1 });

3. 创建带时区的日期时间

// 北京时间
const beijing = Temporal.ZonedDateTime.from(
  '2026-05-20T14:30:00+08:00[Asia/Shanghai]'
);

// 从components创建
const tokyo = Temporal.ZonedDateTime.from({
  year: 2026, month: 5, day: 20,
  hour: 15, minute: 30,
  timeZone: 'Asia/Tokyo'
});

4. 日期加减运算

const today = Temporal.Now.plainDateISO();

// 加3个月
const future = today.add({ months: 3 });

// 减7天
const lastWeek = today.subtract({ days: 7 });

// 加2年3个月15天
const futureDate = today.add({ years: 2, months: 3, days: 15 });

5. 计算两个日期的差

const start = Temporal.PlainDate.from('2026-01-01');
const end = Temporal.PlainDate.from('2026-12-31');

const diff = end.since(start);
console.log(diff.toString());  // P364D

// 按不同单位计算
console.log(end.since(start, { largestUnit: 'months' }).toString());
// P11M30D

console.log(end.since(start, { largestUnit: 'years' }).toString());
// P11M30D

6. 时区转换

const now = Temporal.Now.zonedDateTimeISO();
console.log(now.toString());
// 2026-05-20T14:30:00+08:00[Asia/Shanghai]

// 转换到东京时间
const tokyo = now.withTimeZone('Asia/Tokyo');
console.log(tokyo.toString());
// 2026-05-20T15:30:00+09:00[Asia/Tokyo]

// 转换到纽约时间
const ny = now.withTimeZone('America/New_York');
console.log(ny.toString());
// 2026-05-20T02:30:00-04:00[America/New_York]

7. 格式化输出

const date = Temporal.PlainDate.from('2026-05-20');

// 自定义格式
const formatted = date.toLocaleDateString('zh-CN', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  weekday: 'long'
});
console.log(formatted);  // 2026年5月20日星期三

// ISO格式
console.log(date.toString());  // 2026-05-20

8. 比较日期

const a = Temporal.PlainDate.from('2026-01-01');
const b = Temporal.PlainDate.from('2026-12-31');

console.log(Temporal.PlainDate.compare(a, b));  // -1 (a < b)
console.log(a.equals(b));  // false
console.log(a.toString() === b.toString());  // false

9. Duration(时间段)

// 创建时间段
const dur = Temporal.Duration.from({ hours: 2, minutes: 30 });
console.log(dur.toString());  // PT2H30M

// 用Duration做日期运算
const now = Temporal.Now.zonedDateTimeISO();
const later = now.add(dur);
console.log(later.toString());

// Duration可以规范化
const messy = Temporal.Duration.from({ minutes: 90 });
const normalized = messy.round({ largestUnit: 'hours' });
console.log(normalized.toString());  // PT1H30M

10. 获取日期信息

const date = Temporal.PlainDate.from('2026-05-20');

console.log(date.dayOfWeek);   // 3 (星期三,1=周一,7=周日)
console.log(date.dayOfYear);   // 140
console.log(date.weekOfYear);  // 21
console.log(date.daysInMonth); // 31
console.log(date.inLeapYear);  // false

11. 月份第一天/最后一天

const date = Temporal.Now.plainDateISO();

// 本月第一天
const firstDay = date.with({ day: 1 });

// 本月最后一天
const lastDay = date.with({ day: date.daysInMonth });

// 本年第一天
const yearStart = date.with({ month: 1, day: 1 });

12. 与旧代码互操作

// Temporal → Date
const plainDate = Temporal.PlainDate.from('2026-05-20');
const jsDate = new Date(plainDate.toString());

// Date → Temporal
const fromJsDate = Temporal.Instant.fromEpochMilliseconds(
  jsDate.getTime()
);
const zdt = fromJsDate.toZonedDateTimeISO('Asia/Shanghai');

注意事项

  • 浏览器支持:目前Temporal API主要在Node.js 26+中可用,浏览器支持还在推进中。如果需要在浏览器中使用,可以使用temporal-polyfill
  • 性能:对于简单的日期操作,Date对象可能更快。Temporal的优势在于正确性和可维护性
  • 库兼容性:大部分日期处理库(如date-fns、dayjs)还不直接支持Temporal对象,需要先转换

迁移建议

对于现有项目,不需要立即全面迁移。建议:

  1. 新代码直接使用Temporal API
  2. 在重构日期相关代码时,逐步替换Date对象
  3. 在测试环境中全面验证后再上线

本文参考来源:Node.js 26.0.0 Release Notes | TC39 Temporal Proposal

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容