Node.js的新日期不反映来自.env的时区TZ var

时间:2019-02-04 11:29:51

标签: node.js macos timezone-offset

偶然发现了Node.js和MacOs中的一个有趣的问题-基本上,如果您在.env文件中运行带有设置时区var的node实例,变量TZ,并且您的本地计算机位于不同时区,则Date创建为f * *尽可能以麦芽汁的形式发酵,这样:

时区设置正确

但是,当您创建新的日期时,不会反映时区


请参见此示例,(我的机器在欧洲中部时间(CET),时区为欧洲/布拉格):

~/
11:13 (CET) $ node
new Date()
2019-02-04T10:30:23.053Z # Europe/Prague
new Date().getTimezoneOffset()
-60 # Europe/Prague
.exit

vs。在TZ env中设置时区

✔ ~/
11:30 (CET) $ TZ=America/New_York node
new Date()
2019-02-04T10:31:40.968Z # 10:31! :D
new Date().getTimezoneOffset()
300 # America/New_York!

因此不可能创建一个正确的日期,因为所有的JS库(例如moment)都在Date对象的末尾使用。 我的观点是,您永远不要在运行Node.js服务器时设置TZ var,我会错过什么吗?

2 个答案:

答案 0 :(得分:1)

您可以使用moment-timezone节点程序包解决问题。以下代码可以帮助您解决问题。

const moment = require('moment-timezone')

function convertDate(dateInUTCFormat) { 
    return new Promise((resolve, reject) => { 
        var dec = moment(dateInUTCFormat);
        var normalDate = dec.tz('Asia/Kolkata').format('YYYY-MM-DD');  // GMT +5:30 (India)
        resolve(normalDate);
    }) 
}

此外,您还需要将以2019-02-04T10:30:23.053Z为UTC格式的日期格式传递给convertDate函数,并在我经过时区Asia/Kolkata时传递时区。可能会帮助您找到解决方案。

答案 1 :(得分:1)

您的示例对我来说是正确的。我怀疑您对计算机跟踪和显示时间的看法是颠倒的。您的评论暗示您认为TZ用于从计算机的内部时钟导出UTC。那不是它的工作原理。

在内部,您的Mac使用的是UTC时间。您的Mac在CET中不是。它是“在UTC中,默认TZ设置为CET”。 TZ控制在需要本地时间戳或时区偏移量时如何从基础UTC导出本地时间。如果您更改TZ,则本地时间戳将显示在新时区中,但计算机在UTC中的内部计时不会受到影响。

特别是对于您的示例,new Date()为您提供了一个表示当前时间的Date对象。 Date对象的默认字符串表示形式是UTC时间。在您的示例中,您可以看到这次显示为new Date()调用的结果:

    2019-02-04T10:30:23.053Z # Europe/Prague

是UTC时间,因为其时区显示为Z,表示UTC。 (记住该方法的一种方法是,“ Z”表示“与UTC的零偏移”。这种格式有时也称为“ Zulu”时间,因为“ Zulu”是国际民航组织语音字母的“ Z”代码字。)声称这是欧洲/布拉格当地的时间戳,则注释不正确。

第二个new Date()的结果:

    2019-02-04T10:31:40.968Z # 10:31! :D

也以UTC显示,比第一个结果晚约一分钟。 TZ与此过程不同并不重要,因为TZ不会影响UTC时间戳。

要查看通过将TZ设置应用于从计算机时钟获得的UTC时间而计算出的本地时间,请在toLocaleString对象上使用Date方法。如果您使用该方法重复测试,则会看到以下内容:

    $ env TZ=Europe/Prague node 
    > now = new Date()
    2019-02-04T20:26:40.408Z
    > now.toLocaleString()
    'Mon Feb 04 2019 21:26:40 GMT+0100 (CET)'

    $ env TZ=America/New_York node 
    > now = new Date()
    2019-02-04T20:27:12.438Z
    > now.toLocaleString()
    'Mon Feb 04 2019 15:27:12 GMT-0500 (EST)'

看起来非常合理。

BTW,Node或JavaScript在这里没有做任何异常的事情。这就是它适用于所有事物的方式。例如,date命令:

    $ env TZ=Europe/Prague date
    Mon Feb  4 21:54:49 CET 2019

    $ env TZ=America/New_York date
    Mon Feb  4 15:54:51 EST 2019