JavaScript中的时区:如何不抓狂

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么时间是个麻烦

\n\n

每个写过JavaScript代码的人,都遇到过这种麻烦。你给用户显示时间12:00,他却说:“我这里是14:00,全乱了。”或者你把日期保存到数据库,加载时却倒退了一个小时。熟悉吗?

\n\n

处理JavaScript中的时区是许多开发者“以后再说”的话题。但这是错误的。因为如果不立即搞清楚,以后就得重写一半的应用程序。

\n\n

在本文中,我将讲解如何正确处理JS中的时区,展示真实的代码示例,并给出一些能节省你数小时调试时间的技巧。开始吧!

\n\n

为什么JavaScript处理日期如此奇怪?

\n\n

首先从关键点开始:JavaScript中的Date对象,说白了,并不好用。它以自1970年1月1日UTC以来的毫秒数存储时间。这本身没什么问题,但是:

\n\n
    \n
  • getMonth()返回的月份是从0到11(一月是0,十二月是11)
  • \n
  • getHours()、getMinutes()方法返回的是用户本地时区的时间
  • \n
  • 而getUTCHours()、getUTCMinutes()方法返回的是UTC时间
  • \n
\n\n

混乱就从这里开始。假设你写:

\n\n
const now = new Date();\nconsole.log(now.getHours());      // 14 — 如果你在MSK时区\nconsole.log(now.getUTCHours());   // 11 — UTC
\n\n

如果你把now保存到数据库,然后在另一个时区的服务器上读取它,就会得到混乱的结果。因此,处理JavaScript中的日期和时区的第一条规则是——始终以UTC存储时间,并在客户端进行转换。

\n\n

Intl.DateTimeFormat:内置的救星

\n\n

许多人不知道,现代JavaScript中有一个强大的内置API用于考虑时区的日期格式化。这就是Intl.DateTimeFormat。它支持所有主要时区,并能漂亮地格式化日期。

\n\n

基本示例

\n\n
const date = new Date('2025-03-15T12:00:00Z');\n\nconst formatter = new Intl.DateTimeFormat('ru-RU', {\n    timeZone: 'America/New_York',\n    year: 'numeric',\n    month: 'long',\n    day: 'numeric',\n    hour: '2-digit',\n    minute: '2-digit'\n});\n\nconsole.log(formatter.format(date)); \n// "2025年3月15日,08:00" — 纽约时间
\n\n

请注意:我们传递的是UTC日期(末尾的字母Z),而Intl.DateTimeFormat会自动将其转换为所需的时区。这对于向不同地区的用户显示时间非常理想。

\n\n

所有时区列表

\n\n

如果你不知道指定哪个时区,可以获取完整列表:

\n\n
console.log(Intl.supportedValuesOf('timeZone'));\n// ["Africa/Abidjan", "Africa/Accra", ..., "Pacific/Wallis"]
\n\n

这个列表包含500多个时区。用它来确认你的时区是否被支持。

\n\n

Moment.js:经典,但有保留

\n\n

长期以来,moment.js一直是JavaScript中处理日期的标准。它可以解析、格式化、操作日期,当然,也可以通过插件moment-timezone处理时区。

\n\n

安装

\n\n
npm install moment moment-timezone
\n\n

时区示例

\n\n
const moment = require('moment-timezone');\n\nconst now = moment();\nconsole.log(now.tz('Europe/Moscow').format('YYYY-MM-DD HH:mm'));\n// 2025-03-15 14:00 — 莫斯科时间\n\nconst nyTime = moment.tz('2025-03-15 12:00', 'America/New_York');\nconsole.log(nyTime.clone().tz('Europe/Moscow').format('YYYY-MM-DD HH:mm'));\n// 2025-03-15 19:00 — 相差7小时
\n\n

重要提示: moment.js是一个遗留库。作者自己也建议迁移

博客

书籍推荐