Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
djbeaumont opened this issue Apr 21, 2020 · 9 comments
Closed

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

djbeaumont opened this issue Apr 21, 2020 · 9 comments

Comments

@djbeaumont
Copy link

🐛 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 
@ide
Copy link
Contributor

ide commented Feb 10, 2021

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.)

@djbeaumont
Copy link
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.

@SimenB
Copy link
Member

SimenB commented Feb 10, 2021

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

@djbeaumont
Copy link
Author

djbeaumont commented Feb 10, 2021

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.

@longlho
Copy link

longlho commented Feb 10, 2021

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.

@bmaupin
Copy link

bmaupin commented Nov 10, 2021

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

@StringEpsilon
Copy link
Contributor

Duplicate (or: special case) of #9264

@lazytype
Copy link

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

@github-actions
Copy link

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants