Node: TZ environment variable is being ignored for most time zones

Created on 30 Mar 2020  Â·  6Comments  Â·  Source: nodejs/node

  • Version: 12.14.1 (from my tests, affected versions seem to be at least 10.19.0 - 13.12.0)
  • Platform: Linux pc1 5.5.11-1-MANJARO #1 SMP PREEMPT Sat Mar 21 16:54:29 UTC 2020 x86_64 GNU/Linux
  • Subsystem: ?

What steps will reproduce the bug?

Simple code snippet (as required by the template):

console.log(new Date().getTimezoneOffset(), new Date().toString());

Non-simple version (requiring n for switching node versions):

$ echo; echo -n "current date : "; date; echo -n "with TZ=GMT-4: "; TZ=GMT-4 date; echo -n "with TZ=UTC  : "; TZ=UTC date; echo; p="console.log(new Date().getTimezoneOffset(), new Date().toString())"; for i in {6..13}; do n > /dev/null $i && node -v && echo -n "with TZ=GMT-4: " && TZ=GMT-4 node -e $p; echo -n "with TZ=UTC  : "; TZ=UTC node -e $p; echo; done

current date : Po 30. března 2020, 11:44:11 CEST
with TZ=GMT-4: Po 30. března 2020, 13:44:11 GMT
with TZ=UTC  : Po 30. března 2020, 09:44:11 UTC

v6.17.1
with TZ=GMT-4: -240 'Mon Mar 30 2020 13:44:12 GMT+0400 (GMT)'
with TZ=UTC  : 0 'Mon Mar 30 2020 09:44:12 GMT+0000 (UTC)'

v7.10.1
with TZ=GMT-4: -240 'Mon Mar 30 2020 13:44:12 GMT+0400 (GMT)'
with TZ=UTC  : 0 'Mon Mar 30 2020 09:44:13 GMT+0000 (UTC)'

v8.17.0
with TZ=GMT-4: -240 'Mon Mar 30 2020 13:44:13 GMT+0400 (GMT)'
with TZ=UTC  : 0 'Mon Mar 30 2020 09:44:13 GMT+0000 (UTC)'

v9.11.2
with TZ=GMT-4: -240 'Mon Mar 30 2020 13:44:14 GMT+0400 (GMT)'
with TZ=UTC  : 0 'Mon Mar 30 2020 09:44:14 GMT+0000 (UTC)'

v10.19.0
with TZ=GMT-4: -120 'Mon Mar 30 2020 11:44:15 GMT+0200 (Central European Summer Time)'
with TZ=UTC  : 0 'Mon Mar 30 2020 09:44:15 GMT+0000 (Coordinated Universal Time)'

v11.15.0
with TZ=GMT-4: -120 'Mon Mar 30 2020 11:44:15 GMT+0200 (Central European Summer Time)'
with TZ=UTC  : 0 'Mon Mar 30 2020 09:44:15 GMT+0000 (Coordinated Universal Time)'

v12.16.1
with TZ=GMT-4: -120 Mon Mar 30 2020 11:44:16 GMT+0200 (Central European Summer Time)
with TZ=UTC  : 0 Mon Mar 30 2020 09:44:16 GMT+0000 (Coordinated Universal Time)

v13.12.0
with TZ=GMT-4: -120 Mon Mar 30 2020 11:44:16 GMT+0200 (Central European Summer Time)
with TZ=UTC  : 0 Mon Mar 30 2020 09:44:16 GMT+0000 (Coordinated Universal Time)

Notice the change in behaviour between version 9 to 10. It was working as expected, then suddenly changed to always use local time zone (GMT+2) instead of the given one (GMT+4 which is in POSIX format written as GMT-4).

How often does it reproduce? Is there a required condition?

Every time.

What is the expected behavior?


To respect TZ variable resulting in:

with TZ=GMT-4: -240 'Mon Mar 30 2020 13:44:13 GMT+0400 (GMT)'

Generally, to support all time zones, not only few selected ones like UTC.

What do you see instead?

with TZ=GMT-4: -120 Mon Mar 30 2020 11:44:16 GMT+0200 (Central European Summer Time)

Additional information

If this is an intended behaviour (which would be odd), what is the recommended way of setting non-UTC non-local time zone for a node process? (We can't use local time zone nor UTC, because we need to test few functions which must function when run in other time zones.)

All 6 comments

Timezone handling is delegated to ICU starting in v10.x and ICU uses Olson designators:

$ env TZ=Europe/Samara node -p '[new Date().getTimezoneOffset(), new Date().toString()]'
[ -240, 'Mon Mar 30 2020 15:35:19 GMT+0400 (Samara Standard Time)' ]

What _might_ be a bug is that ICU doesn't seem to understand Etc/GMT-4 even though it knows about Etc/GMT and Etc/UTC (and knows the difference between the two.)

@srl295 Maybe you can shed some light on that?

The Europe/Samara time zone works well (doesn't have daylight saving time which suits us). Thank you.

current date         : Po 30. března 2020, 14:32:31 CEST
with TZ=GMT-4        : Po 30. března 2020, 16:32:31 GMT
with TZ=UTC          : Po 30. března 2020, 12:32:31 UTC
with TZ=GET          : Po 30. března 2020, 16:32:31 +04
with TZ=Europe/Samara: Po 30. března 2020, 12:32:31 GET

v6.17.1
with TZ=GMT-4        : -240 'Mon Mar 30 2020 16:32:31 GMT+0400 (GMT)'
with TZ=UTC          : 0 'Mon Mar 30 2020 12:32:31 GMT+0000 (UTC)'
with TZ=GET          : 0 'Mon Mar 30 2020 12:32:31 GMT+0000 (GET)'
with TZ=Europe/Samara: -240 'Mon Mar 30 2020 16:32:31 GMT+0400 (+04)'

v7.10.1
with TZ=GMT-4        : -240 'Mon Mar 30 2020 16:32:32 GMT+0400 (GMT)'
with TZ=UTC          : 0 'Mon Mar 30 2020 12:32:32 GMT+0000 (UTC)'
with TZ=GET          : 0 'Mon Mar 30 2020 12:32:32 GMT+0000 (GET)'
with TZ=Europe/Samara: -240 'Mon Mar 30 2020 16:32:32 GMT+0400 (+04)'

v8.17.0
with TZ=GMT-4        : -240 'Mon Mar 30 2020 16:32:32 GMT+0400 (GMT)'
with TZ=UTC          : 0 'Mon Mar 30 2020 12:32:33 GMT+0000 (UTC)'
with TZ=GET          : 0 'Mon Mar 30 2020 12:32:33 GMT+0000 (GET)'
with TZ=Europe/Samara: -240 'Mon Mar 30 2020 16:32:33 GMT+0400 (+04)'

v9.11.2
with TZ=GMT-4        : -240 'Mon Mar 30 2020 16:32:33 GMT+0400 (GMT)'
with TZ=UTC          : 0 'Mon Mar 30 2020 12:32:33 GMT+0000 (UTC)'
with TZ=GET          : 0 'Mon Mar 30 2020 12:32:33 GMT+0000 (GET)'
with TZ=Europe/Samara: -240 'Mon Mar 30 2020 16:32:33 GMT+0400 (+04)'

v10.19.0
with TZ=GMT-4        : -120 'Mon Mar 30 2020 14:32:34 GMT+0200 (Central European Summer Time)'
with TZ=UTC          : 0 'Mon Mar 30 2020 12:32:34 GMT+0000 (Coordinated Universal Time)'
with TZ=GET          : 0 'Mon Mar 30 2020 12:32:34 GMT+0000 (GMT)'
with TZ=Europe/Samara: -240 'Mon Mar 30 2020 16:32:34 GMT+0400 (Samara Standard Time)'

v11.15.0
with TZ=GMT-4        : -120 'Mon Mar 30 2020 14:32:35 GMT+0200 (Central European Summer Time)'
with TZ=UTC          : 0 'Mon Mar 30 2020 12:32:35 GMT+0000 (Coordinated Universal Time)'
with TZ=GET          : 0 'Mon Mar 30 2020 12:32:35 GMT+0000 (GMT)'
with TZ=Europe/Samara: -240 'Mon Mar 30 2020 16:32:35 GMT+0400 (Samara Standard Time)'

v12.16.1
with TZ=GMT-4        : -120 Mon Mar 30 2020 14:32:35 GMT+0200 (Central European Summer Time)
with TZ=UTC          : 0 Mon Mar 30 2020 12:32:35 GMT+0000 (Coordinated Universal Time)
with TZ=GET          : 0 Mon Mar 30 2020 12:32:35 GMT+0000 (GMT)
with TZ=Europe/Samara: -240 Mon Mar 30 2020 16:32:35 GMT+0400 (Samara Standard Time)

v13.12.0
with TZ=GMT-4        : -120 Mon Mar 30 2020 14:32:36 GMT+0200 (Central European Summer Time)
with TZ=UTC          : 0 Mon Mar 30 2020 12:32:36 GMT+0000 (Coordinated Universal Time)
with TZ=GET          : 0 Mon Mar 30 2020 12:32:36 GMT+0000 (GMT)
with TZ=Europe/Samara: -240 Mon Mar 30 2020 16:32:36 GMT+0400 (Samara Standard Time)

"GMT-4" is not a valid id, that's the short of it.

"GMT-4" is not a valid id, that's the short of it.

According to https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html the format EST+5 (so I expect GMT-4) is a valid value of TZ in POSIX.1. The date command correctly interprets it, but node is ignoring it.

In POSIX.1 systems the value of the TZ variable can be in one of three formats.
...
The first format is used when there is no Daylight Saving Time (or summer time) in the local time zone:
std offset
...
For example, here is how we would specify Eastern Standard Time, but without any Daylight Saving Time alternative:
EST+5

"GMT-4" is not a valid id, that's the short of it.

According to https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html the format EST+5 (so I expect GMT-4) is a valid value of TZ in POSIX.1. The date command correctly interprets it, but node is ignoring it.

  • short workaround: try "Etc/GMT-4" which is a real zone.

But a question: where do you (or your server) actually live? With a raw offset, there's no hope to localize the name of your zone. Yes there are three formats, but please don't use the first two. Even the document you linked recommends against it.

Yes I know of the posix format. But I'd rather not see it propagated. You can file a bug upstream in icu or even contribute it there (there's probably already one).

@mnn also… my apologies for not getting back to you sooner on this issue! I know it was a long time ago.

@bnoordhuis thanks for the mention- going forward please mention the whole team @nodejs/i18n-api thanks !

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cong88 picture cong88  Â·  3Comments

jmichae3 picture jmichae3  Â·  3Comments

filipesilvaa picture filipesilvaa  Â·  3Comments

stevenvachon picture stevenvachon  Â·  3Comments

addaleax picture addaleax  Â·  3Comments