- 原文地址:How to Handle Time Zones in JavaScript
- 原文作者:Ravidu Perera
- 译文出自:掘金翻译计划
了解JavaScript中处理时区的各种方法。

在构建Web应用程序时,我们通常会考虑两种类型的时区。最常见的是服务器时间,它作为日期和时间跟踪的参考,非常简单直观。
但是,在某些情况下,我们需要跟踪最终用户的日期和时间。在这些情况下,我们需要使用 JavaScript 从用户的浏览器中捕获时间。此外,这些用户可能来自不同的时区,处理起来可能比较棘手。
本文将讨论与时区相关的概念以及使用 JavaScript 处理时区的方法。
GMT 时区,偏移量, UTC

在开始讨论细节之前,让我们先了解一些关于时区的术语。
1. GMT - 通用参照物
世界被划分为时区,每个时区都有其偏移量。此偏移量是一个分钟数,用于计算每个国家所处时区与世界时间的偏差。
为此,我们需要一个参照物,即格林威治标准时间(GMT)。它从北极到南极,经过伦敦旧皇家天文台所在的格林威治区。
如果你在格林威治子午线(又叫本初子午线)以东,你的当地时间通常早于格林威治标准时间(例如,中国的当地时间是格林威治标准时间+8小时)。相反,如果在格林威治子午线以西,当地时间就会落后于格林威治标准时间(例如,纽约当地时间在冬季为格林威治标准时间 -5小时,夏季为格林威治标准时间 -4小时)。
2. 偏移量-与参照物的偏差
时区的偏移量指的是比**GMT格林威治标准时间早或者晚的小时数或分钟数。
因为存在夏令时,时区的偏移量可能会在一年中发生变化。此外,法律可以改变时区的偏移量或夏令时。例如,当我们说印第安纳州从中部时间切换到东部时间时,印第安纳州的时区从一个偏移量切换到另一个偏移量。
各国通常以自己的名字命名时区。例如,韩国的时区称为KST(韩国标准时间),其特定偏移值为_KST=UTC+09:00。
3. UTC — 比GMT更好的替代方案
许多人错误地认为GMT和UTC是相同的东西,经常互换使用。但是如果我告诉你它们不一样呢?
UTC创立于1972年,旨在解决地球自转减速问题。本时间系统以国际原子时为基准,采用铯原子频率设置时间标准。换句话说,UTC是GMT更好的替代品。但是,这种差异在日常发展中几乎不明显。
var d = new Date();
var n = d.getTimezoneOffset(); // Returns UTC Offset in Minutes
在实际中使用JavaScript进行日期时间处理
JavaScript为日期对象提供了各种方法来执行与日期和时间相关的计算。您可以选择使用它,也可以使用更多增强的库在代码中执行日期时间处理。让我们首先看看我们可以从JavaScript日期对象中得到了什么。
日期时间操作 - 使用原生 JavaScript
JavaScript中的Date对象在内部使用绝对数(如Unix时间)管理时间数据。如parse(), getHour(), setHour()这样的构造函数和方法,
然而,需要注意的是,它受客户端的本地时区(确切地说是运行浏览器的操作系统的时区)的影响。因此,从用户输入数据生成的日期对象将表示客户端的本地时区。Date对象在内部以UTC记录时间,但它通常在运行它的计算机的本地时间接收和输出数据。
但是,在JavaScript中,在跨不同时区进行日期时间计算时,原生可用的方法十分有限。
但是,date对象可以对非本地时区执行一个操作。
ISOString — 它可以转换包含任何时区的数字化UTC偏移量的文本。输出的日期对象不会保留原来的本地时间和偏移量。
var d = new Date();
d.toISOString(); //=> "2021-09-06T13:52:23.770Z"
d.valueOf(); //=> 1630936367439 (this is what is actually stored in the object)
Date Time 操作-使用第三方库
有许多库提供了众多的日期格式化和操作功能。根据这些库是否支持ECMAScript国际化API,我们可以将它们分为两种类型。
基于Intl的库
新的开发项目应当使用以下时区实现之一,这些时区实现对其数据使用Intl API:
-
date-fns-tz (date-fns 的扩展)
不基于Intl的库
这些库仍在保持更新,但它们只对他们封装的、重要的时区数据负责。
-
js-joda/timezone ( js-joda 的扩展)
-
date-fns-timezone ( date-fns 旧的 1.x 版本的扩展)
此外,新项目避免使用一些已经停止维护的库也十分重要。
停止维护的项目
这些库已经正式停止维护,不应该再被使用了。
除了这些,我相信你们中的大多数人都熟悉Moment,但是Moment团队现在推荐使用Luxon。
当您尝试使用嵌入式的库时,我的建议是先读文档。然后,在您了解了一些基本知识之后,尝试将其应用到您的代码中。
我的最爱 — Date-fns
Date fns是一个小型库,它有一个简单的API,有许多小函数可供使用。Date fns具有近140个功能,被称为日期库里的Lodash。
Date-fns 有以下优点:
-
不可变和纯净
-
当地日起
-
模块化
-
快速
-
良好的文档
-
I18n 国际化
-
基于Typescript
npm 包管理器已经集成了 Date-fns. 你可以使用命令 npm install date-fns安装 date-fns。
Date fns 同时兼容 CommonJS 和 ES Module 。
您需要导入解析和显示日期所需的函数;您不需要导入整个API(只导入您需要的内容)。让我们只显示当前日期。
//Import the function initially
const { format } = require('date-fns');
//today's date
const today = format(new Date(), 'dd.MM.yyyy');
console.log(today);
使用时区
要使用UTC或ISO日期字符串,Date-fns 支持时区数据。这将允许您以用户的本地时间显示日期和时间。当使用多个时区时,挑战就来了。让我们通过一个例子来了解如何处理这些情况。
-
参考点— 首先, 用一个时间戳、UTC时间、或者ISO时间字符串表示一个固定的时间点。
-
指定时区 — 然后, 时区描述符 (例如. America/Los Angeles) 通常是偏移量或IANA时区名称。
Note: 你需要使用
npm install date-fns-tz安装 date-fns-tz 库。
- 时区时间转 UTC

- UTC转时区时间

结论
许多库都可以处理时区。它们通常实现标准的IANA时区数据库,并提供在JavaScript中使用它的函数,但是他们不会改变 Date 对象的行为。
现代的库使用 Intl API 的时区数据,而旧的库通常在web浏览器中运行时开销巨大,因为数据库可能会变得相当大。
总之,如果您为新项目选择库,请选择支持 Intl API 的库,这些库是未来正确的选择。否则,如果您只处理了几个日期时间操作,则使用原生日期对象也没问题。
我希望本文能够帮助您确定在JavaScript中使用时区时要考虑的各种因素。如果您有任何其他建议,请在下面的评论中提供。
感谢阅读本文!!