mppub
mppub

Reputation: 11

Node.js new Date does not reflect timezone TZ var from .env

just stumbled upon one funny issue in Node.js & MacOs - basically if you run instance of node with set timezone var in .env file, variable TZ, and you local machine is in different timezone, the Date creation is f**d up in the wort way possible, so that:

Timezone is set correctly

But when you create a new Date, the timezone is not reflected


see this example, (my machine is in CET, timezone Europe/Prague) :

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

vs. set timezone in 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!

So it is not possible to create a correct date then, since all JS libs like moment uses in the end Date object. My take is that you should never ever set TZ var while running Node.js server, do I miss something?

Upvotes: 1

Views: 4685

Answers (2)

ottomeister
ottomeister

Reputation: 5808

Your examples look correct to me. I suspect that your notion of the way the computer keeps track of, and shows, time is upside-down. Your comments imply that you think TZ is used to derive UTC from the computer's internal clock. That's not how it works.

Internally, your Mac is using UTC time. Your Mac is not "in CET". It is "in UTC with a default TZ setting of CET". TZ controls how a local time is derived from the underlying UTC when a local timestamp or timezone offset is required. If you change TZ then local timestamps will be shown in the new timezone, but the computer's internal timekeeping in UTC is not affected.

Specifically for your example, new Date() gets you a Date object representing the current time. The default string representation of a Date object is the UTC time. In your example you can see that this time, shown as the result of the new Date() call:

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

is a UTC time because its timezone is shown as Z, indicating UTC. (One way to remember that meaning is that "Z" is for "Zero offset from UTC". This format is sometimes called "Zulu" time because "Zulu" is the ICAO phonetic alphabet's code word for "Z".) If your comment is claiming that this is a local Europe/Prague timestamp then the comment is incorrect.

The result of the second new Date():

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

is also shown in UTC and is about a minute later than the first result. It doesn't matter that TZ for this process is different, because TZ does not affect UTC timestamps.

To see the local time, which is calculated by applying the TZ setting to the UTC time obtained from the computer's clock, use the toLocaleString method on the Date object. If you repeat your test using that method you'll see something like this:

    $ 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)'

which looks perfectly reasonable.

BTW, Node, or JavaScript, isn't doing anything unusual here. This is the way it works for everything. For example, the date command:

    $ 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

Upvotes: 3

pradip shinde
pradip shinde

Reputation: 586

You can solve your issue with moment-timezone node package. below code may help you to resolve your issue.

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);
    }) 
}

Also you need to pass the date format that you get in UTC format for eg 2019-02-04T10:30:23.053Z to convertDate function and pass your timezone as i passed my timezone Asia/Kolkata . May this will help you to find your solution.

Upvotes: 1

Related Questions