在 Javascript 中使用不同的时区

Ish*_*ngi 4 javascript timezone datetime date

我正在开发一个基于云的应用程序,它为世界各地的用户广泛处理日期和时间值。

考虑一个场景,在 JavaScript 中,我的机器在印度 (GMT+05:30),我必须显示在加利福尼亚时区 (GMT-08:00) 运行的时钟。

在这种情况下,我必须获得一个新的日期对象,

let india_date = new Date()

添加它的时区偏移值,

let uts_ms = india_date.getTime() + india_date.getTimezoneOffset()

添加加利福尼亚的时区偏移值,

let california_ms = utc_ms + getCaliforniaTimezoneOffsetMS()

最后是日期对象。

let california_date: Date = new Date(california_ms)

有没有办法直接处理这些类型的时区而不必一次又一次地转换值?

ben*_*nvc 7

JavaScript Date 对象以 UTC 格式存储日期和时间,但当toString()日期表示为显示浏览器本地时区中的日期和时间的文本值时,会自动调用该方法。因此,当您想要将日期时间转换为本地时间以外的时区时,您实际上是从 UTC 转换为该时区(而不是从本地时区转换为另一个时区)。

如果您的用例仅限于特定浏览器并且您对格式很灵活(因为浏览器显示日期字符串格式的方式可能有所不同),那么您可能可以使用toLocaleString(),但 Edge、Android webview 等浏览器不完全支持和locales参数options

以下示例设置区域设置和时区以以本地格式输出日期,该格式可能因浏览器而异。

const dt = new Date();
const kolkata = dt.toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' });
const la = dt.toLocaleString('en-US', { timeZone: 'America/Los_Angeles' });
console.log('Kolkata:', kolkata);
// example output: Kolkata: 19/3/2019, 7:36:26 pm
console.log('Los Angeles:', la);
// example output: Los Angeles: 3/19/2019, 7:06:26 AM
Run Code Online (Sandbox Code Playgroud)

您还可以使用Moment.jsMoment Timezone将日期和时间转换为本地时区以外的时区。例如:

const dt = moment();
const kolkata = dt.tz('Asia/Kolkata').format();
const la = dt.tz('America/Los_Angeles').format();
console.log(kolkata);
// example output: 2019-03-19T19:37:11+05:30
console.log(la);
// example output: 2019-03-19T07:07:11-07:00
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.23/moment-timezone-with-data.min.js"></script>
Run Code Online (Sandbox Code Playgroud)


Mat*_*int 5

首先,让我们谈谈您的问题中的代码。

let india_date = new Date()
Run Code Online (Sandbox Code Playgroud)

您已将此变量命名为india_date,但Date只有在设置为印度时区的计算机上运行代码时,该对象才会反映印度。如果它在具有不同时区的计算机上运行,​​它将改为反映该时区。请记住,在内部,该Date对象仅跟踪基于 UTC 的时间戳。在调用需要本地时间的函数和属性时应用本地时区 - 而不是在Date创建对象时。

添加它的时区偏移值

let uts_ms = india_date.getTime() + india_date.getTimezoneOffset()
Run Code Online (Sandbox Code Playgroud)

这种做法是不正确的。 getTime()已经返回基于 UTC 的时间戳。您不需要添加本地偏移量。(另外,缩写是 UTC,而不是 UTS。)

现在添加加利福尼亚的时区偏移值

let california_ms = utc_ms + getCaliforniaTimezoneOffsetMS()
Run Code Online (Sandbox Code Playgroud)

同样,添加偏移量是不正确的。此外,与印度不同的是,加利福尼亚州遵守夏令时,因此一年中的一部分偏移量将是480(UTC-8),而一年中的一部分偏移量将是420(UTC-7)。任何像您getCaliforniatimezoneOffsetMS这样的函数都需要将时间戳作为参数传入才能生效。

最后是日期对象

let california_date: Date = new Date(california_ms)
Run Code Online (Sandbox Code Playgroud)

Date构造函数传递一个数字时间戳时,它必须是 UTC。传递这个california_ms时间戳实际上只是选择了一个不同的时间点。您不能Date仅通过添加或减去偏移量来更改对象的行为以使其使用不同的时区。对于任何需要本地时间的函数,例如.toString()和其他函数,它仍将使用它运行所在位置的本地时区。

只有一种情况可以使这种调整有意义,即一种称为“时代转移”的技术。时间戳被调整以将基本纪元从 normal 移开1970-01-01T00:00:00Z,从而允许利用Date对象的 UTC 功能(例如getUTCHours和其他功能)。问题是:一旦转移,您就不能在该Date对象上使用任何本地时间函数,也不能将其传递给任何其他希望该Date对象是正常对象的对象。正确完成时代转移是像Moment.js这样的库的动力是另一个正确完成时代转移的例子。

但是在您的示例中,您正在移动(错误两次),然后将Date对象用作正常而不是移动的对象。这只会导致错误,这在toString输出中显示的时区很明显,并且会在本地时区和预期目标时区的任何 DST 转换附近在数学上出现。通常,您不想采用这种方法。

相反,请阅读我关于如何将 JavaScript 日期初始化为特定时区的答案 您的选项列在那里。谢谢。