Skip to content

Setting process.env.TZ does not affect Dates聽#9856

Closed

Description

@djbeaumont

馃悰 Bug Report

Nodejs 13+ allows for setting process.env.TZ and having it affect new Dates created at runtime. You can try this in a repl with the following (comments are the dates output on my system):

console.log(process.env.TZ); // undefined
console.log(new Date().toString()); // Tue Apr 21 2020 22:05:28 GMT+0100 (British Summer Time)
process.env.TZ = 'Asia/Kolkata'; // not my timezone
console.log(new Date().toString()); // Wed Apr 22 2020 02:35:28 GMT+0530 (India Standard Time)

This also works in a simple node script (i.e. node test.js) or in the mocha testing library.

Doing the same in jest, either with the lines copied into an test, or some variation where the timezone is set in beforeEach(), does not work. The time printed before and after setting the timezone is the same, ignoring the change in system timezone.

To Reproduce

Steps to reproduce the behavior:

describe('changing the timezone', () => {
  it('resets the nodejs timezone cache', () => {
    console.log(process.env.TZ); // undefined
    console.log(new Date().toString()); // Tue Apr 21 2020 22:36:08 GMT+0100 (British Summer Time)
    process.env.TZ = 'Asia/Kolkata'; // not my timezone
    console.log(new Date().toString()); // Tue Apr 21 2020 22:36:08 GMT+0100 (British Summer Time)
  });
});

Expected behavior

Note that that the date serialisation should be affected by the timezone in the second console.log()

describe('changing the timezone', () => {
  it('resets the nodejs timezone cache', () => {
    console.log(process.env.TZ); // undefined
    console.log(new Date().toString()); // Tue Apr 21 2020 22:37:36 GMT+0100 (British Summer Time)
    process.env.TZ = 'Asia/Kolkata'; // not my timezone
    console.log(new Date().toString()); // Wed Apr 22 2020 03:07:36 GMT+0530 (India Standard Time)
  });
});

Link to repl or repo (highly encouraged)

Unfortunately the linked repl uses nodejs 12 and so won't benefit from the change merged in nodejs 13.

envinfo

$ npx envinfo --preset jest
npx: installed 1 in 1.318s

  System:
    OS: macOS 10.15.4
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
  Binaries:
    Node: 14.0.0 - ~/.nvm/versions/node/v14.0.0/bin/node
    Yarn: 1.22.4 - /usr/local/bin/yarn
    npm: 6.14.4 - ~/.nvm/versions/node/v14.0.0/bin/npm
  npmPackages:
    jest: ^24.9.0 => 24.9.0 

Activity

  1. ide commented on Feb 10, 2021

    @ide
    Contributor

    I suspect the reason this happens is because tests intentionally don't have access to the real process.env object: https://github.com/facebook/jest/blob/5ba0cc9cd3bd865cc3ad08e34e023a1e9aee7d6b/packages/jest-util/src/createProcessObject.ts#L19-L80
    console.log(util.types.isProxy(process.env)) prints true inside Jest and false in a regular Node REPL.

    Practically speaking, the alternatives are to lose isolation between concurrent tests by turning process.env into shared, mutable state or to write a custom Jest environment that spawns processes instead of V8 contexts.

    (Also, if you want to set an environment variable across all tests, you can write to the real process.env in the global setup script.)

  2. djbeaumont commented on Feb 10, 2021

    @djbeaumont
    Author

    Yep, I realised not long after writing this issue by going through the jest setup code. It's a bit frustrating this can't be done (I do a lot of work with timezones...) but understandable.

  3. SimenB commented on Feb 10, 2021

    @SimenB
    Member

    FWIW, we do TZ=UTC jest at work to have it work consistently on CI and locally, but we don't need to switch between timezones so maybe not applicable here. Not sure we can do much about mutating process.env - it would break the isolation and I'm not sure how to properly propagate it.

    I'd probably use some formatter other than toString. Node 14 ships with full ICU, so "just" using https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat is probably a better approach?


    Date being affected by environment variables is sorta horrible TBH 馃槢 Can't wait for https://github.com/tc39/proposal-temporal

  4. djbeaumont commented on Feb 10, 2021

    @djbeaumont
    Author

    Date being affected by environment variables is sorta horrible TBH

    Not going to disagree!
    I'm making an industry specific calendaring system. Our use case was to have something like this:

    describe.each`
      timezone           | other data...
      UTC                   | ...
      Europe/London | ...
      India/Kolkata     | ...
    `('when the event is created in $timezone', () => {
        // ...
      })
    

    But since part of the codebase uses Date/moment to new up instances that relies on the current environment. Think of testing a big formik form as if you were in that country.

    For anyone googling this issue, the workaround we've used for now is to use npm scripts to run the test in several timezones using the real unix environment variables. That works, but is a bit limiting as we can't really test what happens when data goes between timezones well.

  5. longlho commented on Feb 10, 2021

    @longlho

    I don't think Temporal is gonna solve this issue. DefaultTimeZone is a host-specific operation in the spec which is what process.env.TZ controls. So if that needs to change, technically the host/sandbox needs to be rebooted.

    Right now the workaround is to actually polyfill so u have control over tz... it's not great.

  6. bmaupin commented on Nov 10, 2021

    @bmaupin

    I just ran into this behaviour before running across this bug. Not sure if it helps but I created a couple reproducible test cases: https://github.com/bmaupin/jest-timezone-bug

  7. StringEpsilon commented on Feb 27, 2022

    @StringEpsilon
    Contributor

    Duplicate (or: special case) of #9264

  8. lazytype commented on Feb 27, 2022

    @lazytype

    See #9264 (comment) for potential Jest 28-specific solution

  9. github-actions commented on Mar 30, 2022

    @github-actions

    This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
    Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

  10. locked as resolved and limited conversation to collaborators on Mar 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions