Skip to content

Commit 1d1ab76

Browse files
bnoordhuisBridgeAR
authored andcommitted
src: make process.env.TZ setter clear tz cache
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: #20026 Fixes: #19974 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 5af28c2 commit 1d1ab76

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

src/node.cc

+10
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
#include <stdlib.h>
8181
#include <string.h>
8282
#include <sys/types.h>
83+
#include <time.h> // tzset(), _tzset()
8384

8485
#include <string>
8586
#include <vector>
@@ -135,6 +136,7 @@ using v8::Array;
135136
using v8::ArrayBuffer;
136137
using v8::Boolean;
137138
using v8::Context;
139+
using v8::Date;
138140
using v8::EscapableHandleScope;
139141
using v8::Exception;
140142
using v8::Float64Array;
@@ -2679,6 +2681,10 @@ static void EnvSetter(Local<Name> property,
26792681
node::Utf8Value key(info.GetIsolate(), property);
26802682
node::Utf8Value val(info.GetIsolate(), value);
26812683
setenv(*key, *val, 1);
2684+
if (key.length() == 2 && key[0] == 'T' && key[1] == 'Z') {
2685+
tzset();
2686+
Date::DateTimeConfigurationChangeNotification(info.GetIsolate());
2687+
}
26822688
#else // _WIN32
26832689
node::TwoByteValue key(info.GetIsolate(), property);
26842690
node::TwoByteValue val(info.GetIsolate(), value);
@@ -2687,6 +2693,10 @@ static void EnvSetter(Local<Name> property,
26872693
if (key_ptr[0] != L'=') {
26882694
SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
26892695
}
2696+
if (key.length() == 2 && key[0] == L'T' && key[1] == L'Z') {
2697+
_tzset();
2698+
Date::DateTimeConfigurationChangeNotification(info.GetIsolate());
2699+
}
26902700
#endif
26912701
// Whether it worked or not, always return value.
26922702
info.GetReturnValue().Set(value);

test/parallel/test-process-env-tz.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
6+
if (common.isWindows) // Using a different TZ format.
7+
common.skip('todo: test on Windows');
8+
9+
if (common.isAIX || common.isSunOS) // Reports 2018 CEST as CET.
10+
common.skip('tzdata too old');
11+
12+
const date = new Date('2018-04-14T12:34:56.789Z');
13+
14+
process.env.TZ = 'Europe/Amsterdam';
15+
if (/\(Europe\)/.test(date.toString()))
16+
common.skip('not using bundled ICU'); // Shared library or --with-intl=none.
17+
assert.strictEqual(date.toString(), 'Sat Apr 14 2018 14:34:56 GMT+0200 (CEST)');
18+
19+
process.env.TZ = 'Europe/London';
20+
assert.strictEqual(date.toString(), 'Sat Apr 14 2018 13:34:56 GMT+0100 (BST)');
21+
22+
process.env.TZ = 'Etc/UTC';
23+
assert.strictEqual(date.toString(), 'Sat Apr 14 2018 12:34:56 GMT+0000 (UTC)');

0 commit comments

Comments
 (0)