← 返回题目列表

JavaScript Date、时间戳和时区有哪些常见坑?

中等 第 28 / 29 题 更新于 2026/07/29
JavaScriptDate时区

简化版

Date 内部本质保存的是时间戳,表示从 UTC 1970-01-01 00:00:00 起经过的毫秒数。时区主要影响格式化展示和字符串解析,不影响同一个绝对时间点本身。

常见坑包括:月份从 0 开始、日期字符串解析存在差异、YYYY-MM-DD 可能按 UTC 解释、时间戳有秒和毫秒两种单位、夏令时会影响本地时间加减。

详细版

const d = new Date("2026-07-29T10:00:00Z");

console.log(d.getTime()); // 毫秒时间戳
console.log(d.toISOString()); // UTC 字符串
console.log(d.getMonth()); // 6,表示 7 月

时间戳单位要看清:

const ms = 1785319200000;
const sec = 1785319200;

new Date(ms); // 正常
new Date(sec); // 1970 年附近,因为 Date 需要毫秒

工程上建议:接口传输用 ISO 8601 或毫秒时间戳;展示时明确指定时区和格式;不要用本地时间字符串做跨端协议。

完整版教学

一、Date 内部保存的是绝对时间点

Date 对象内部保存的是一个数字:UTC 毫秒时间戳。

const now = new Date();
console.log(now.getTime());

同一个时间戳在上海、纽约、伦敦展示出来的本地时间不同,但它指向的是同一个瞬间。

时区问题的关键是区分“绝对时间点”和“本地展示形式”。

二、UTC 和本地时间 API 要分清

getFullYeargetMonthgetDate 按本地时区取值。

getUTCFullYeargetUTCMonthgetUTCDate 按 UTC 取值。

const d = new Date("2026-01-01T00:30:00Z");

console.log(d.getUTCFullYear());
console.log(d.getFullYear());

如果用户在 UTC-8,第二个结果可能仍是上一年的本地日期。

三、月份从 0 开始

构造函数 new Date(year, monthIndex, day) 的月份从 0 开始。

表达式含义
new Date(2026, 0, 1)2026 年 1 月 1 日
new Date(2026, 6, 29)2026 年 7 月 29 日

这个设计来自早期 API,面试和业务里都很容易犯错。

四、字符串解析要谨慎

ISO 字符串最稳定:

new Date("2026-07-29T10:00:00Z");

本地格式字符串不适合作协议:

new Date("07/29/2026");

不同运行环境可能有不同解析行为。跨端接口更推荐传 ISO 8601、毫秒时间戳,或者明确字段 { year, month, day }

五、秒和毫秒的单位坑

JavaScript Date 构造函数接收毫秒。

const fromServer = 1785319200; // 秒
const date = new Date(fromServer * 1000);

如果后端传 Unix timestamp,通常是秒;前端 Date.now() 返回的是毫秒。两者差 1000 倍。

六、本地日期加减会遇到夏令时

有夏令时地区,一天不一定总是 24 小时。

const oneDay = 24 * 60 * 60 * 1000;

用毫秒加一天适合绝对时间点移动,但不一定等价于本地日历日期加一天。日历计算更适合使用成熟日期库或 Temporal 相关方案。

七、常见误区与追问

  • 误区:Date 对象里存着本地时区。 它主要存 UTC 毫秒时间戳,本地时区影响读取和展示。
  • 误区:getMonth() 返回自然月份。 它从 0 开始,7 月返回 6。
  • 误区:后端时间戳都能直接 new Date。 要确认单位是秒还是毫秒。
  • 误区:所有日期字符串解析都一样。 非标准格式可能受环境影响。
  • 追问:为什么跨时区展示会差一天? UTC 时间点转换成本地日期时可能落在前一天或后一天。
  • 追问:接口应该传什么时间格式? 通常传 ISO 8601 或毫秒时间戳,并约定时区语义。

八、加强记忆

记忆图:

timestamp(ms, UTC)
  ├─ toISOString() -> UTC text
  ├─ getUTC*()     -> UTC fields
  └─ get*()        -> local fields

答题时先讲 Date 内部是 UTC 毫秒,再讲展示受时区影响,最后列出月份从 0、秒毫秒、字符串解析、夏令时这四个常见坑。