Skip to content

Commit

Permalink
src: make process.env.TZ setter clear tz cache
Browse files Browse the repository at this point in the history
Since the presence of the libc and V8 timezone caches seem to be
a perennial source of confusion to users ("why doesn't it work?!"),
let's try to support that pattern by intercepting assignments to
the `TZ` environment variable and reset the caches as a side effect.

PR-URL: nodejs#20026
Fixes: nodejs#19974
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Tiancheng "Timothy" Gu <[email protected]>
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: James M Snell <[email protected]>
  • Loading branch information
bnoordhuis authored and BridgeAR committed Apr 23, 2018
1 parent 5af28c2 commit 1d1ab76
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h> // tzset(), _tzset()

#include <string>
#include <vector>
Expand Down Expand Up @@ -135,6 +136,7 @@ using v8::Array;
using v8::ArrayBuffer;
using v8::Boolean;
using v8::Context;
using v8::Date;
using v8::EscapableHandleScope;
using v8::Exception;
using v8::Float64Array;
Expand Down Expand Up @@ -2679,6 +2681,10 @@ static void EnvSetter(Local<Name> property,
node::Utf8Value key(info.GetIsolate(), property);
node::Utf8Value val(info.GetIsolate(), value);
setenv(*key, *val, 1);
if (key.length() == 2 && key[0] == 'T' && key[1] == 'Z') {
tzset();
Date::DateTimeConfigurationChangeNotification(info.GetIsolate());
}
#else // _WIN32
node::TwoByteValue key(info.GetIsolate(), property);
node::TwoByteValue val(info.GetIsolate(), value);
Expand All @@ -2687,6 +2693,10 @@ static void EnvSetter(Local<Name> property,
if (key_ptr[0] != L'=') {
SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
}
if (key.length() == 2 && key[0] == L'T' && key[1] == L'Z') {
_tzset();
Date::DateTimeConfigurationChangeNotification(info.GetIsolate());
}
#endif
// Whether it worked or not, always return value.
info.GetReturnValue().Set(value);
Expand Down
23 changes: 23 additions & 0 deletions test/parallel/test-process-env-tz.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict';

const common = require('../common');
const assert = require('assert');

if (common.isWindows) // Using a different TZ format.
common.skip('todo: test on Windows');

if (common.isAIX || common.isSunOS) // Reports 2018 CEST as CET.
common.skip('tzdata too old');

const date = new Date('2018-04-14T12:34:56.789Z');

process.env.TZ = 'Europe/Amsterdam';
if (/\(Europe\)/.test(date.toString()))
common.skip('not using bundled ICU'); // Shared library or --with-intl=none.
assert.strictEqual(date.toString(), 'Sat Apr 14 2018 14:34:56 GMT+0200 (CEST)');

process.env.TZ = 'Europe/London';
assert.strictEqual(date.toString(), 'Sat Apr 14 2018 13:34:56 GMT+0100 (BST)');

process.env.TZ = 'Etc/UTC';
assert.strictEqual(date.toString(), 'Sat Apr 14 2018 12:34:56 GMT+0000 (UTC)');

0 comments on commit 1d1ab76

Please sign in to comment.