Skip to content

Commit e59351b

Browse files
committed
lib: support setting process.env.TZ on windows
Fixes: #4230 Signed-off-by: James M Snell <[email protected]>
1 parent 184e0f7 commit e59351b

File tree

5 files changed

+50
-4
lines changed

5 files changed

+50
-4
lines changed

src/node.cc

+8
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,14 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
937937
return 9;
938938
}
939939
per_process::metadata.versions.InitializeIntlVersions();
940+
941+
# ifndef __POSIX__
942+
std::string tz;
943+
if (credentials::SafeGetenv("TZ", &tz) && !tz.empty()) {
944+
i18n::SetDefaultTimeZone(tz.c_str());
945+
}
946+
# endif
947+
940948
#endif
941949

942950
NativeModuleEnv::InitializeCodeCache();

src/node_env_var.cc

+19-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "env-inl.h"
33
#include "node_errors.h"
44
#include "node_external_reference.h"
5+
#include "node_i18n.h"
56
#include "node_process.h"
67

78
#include <time.h> // tzset(), _tzset()
@@ -69,15 +70,29 @@ std::shared_ptr<KVStore> system_environment = std::make_shared<RealEnvStore>();
6970
} // namespace per_process
7071

7172
template <typename T>
72-
void DateTimeConfigurationChangeNotification(Isolate* isolate, const T& key) {
73+
void DateTimeConfigurationChangeNotification(Isolate* isolate, const T& key, const char* val = nullptr) {
7374
if (key.length() == 2 && key[0] == 'T' && key[1] == 'Z') {
7475
#ifdef __POSIX__
7576
tzset();
77+
isolate->DateTimeConfigurationChangeNotification(
78+
Isolate::TimeZoneDetection::kRedetect);
7679
#else
7780
_tzset();
81+
82+
# if defined(NODE_HAVE_I18N_SUPPORT)
83+
isolate->DateTimeConfigurationChangeNotification(
84+
Isolate::TimeZoneDetection::kSkip);
85+
86+
// On windows, the TZ environment is not supported out of the box.
87+
// By default, v8 will only be able to detect the system configured
88+
// timezone. This supports using the TZ environment variable to set
89+
// the default timezone instead.
90+
if (val != nullptr) i18n::SetDefaultTimeZone(val);
91+
# else
92+
isolate->DateTimeConfigurationChangeNotification(
93+
Isolate::TimeZoneDetection::kRedetect);
94+
# endif
7895
#endif
79-
auto constexpr time_zone_detection = Isolate::TimeZoneDetection::kRedetect;
80-
isolate->DateTimeConfigurationChangeNotification(time_zone_detection);
8196
}
8297
}
8398

@@ -128,7 +143,7 @@ void RealEnvStore::Set(Isolate* isolate,
128143
if (key.length() > 0 && key[0] == '=') return;
129144
#endif
130145
uv_os_setenv(*key, *val);
131-
DateTimeConfigurationChangeNotification(isolate, key);
146+
DateTimeConfigurationChangeNotification(isolate, key, *val);
132147
}
133148

134149
int32_t RealEnvStore::Query(const char* key) const {

src/node_i18n.cc

+8
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,14 @@ bool InitializeICUDirectory(const std::string& path) {
542542
return status == U_ZERO_ERROR;
543543
}
544544

545+
void SetDefaultTimeZone(const char* tzid) {
546+
UChar lbl[255];
547+
UErrorCode status = U_ZERO_ERROR;
548+
u_charsToUChars(tzid, lbl, strlen(tzid) + 1);
549+
ucal_setDefaultTimeZone(lbl, &status);
550+
CHECK(U_SUCCESS(status));
551+
}
552+
545553
int32_t ToUnicode(MaybeStackBuffer<char>* buf,
546554
const char* input,
547555
size_t length) {

src/node_i18n.h

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ namespace i18n {
4040

4141
bool InitializeICUDirectory(const std::string& path);
4242

43+
void SetDefaultTimeZone(const char* tzid);
44+
4345
enum idna_mode {
4446
// Default mode for maximum compatibility.
4547
IDNA_DEFAULT,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use strict';
2+
3+
require('../common');
4+
const assert = require('assert');
5+
6+
process.env.TZ = 'Etc/UTC';
7+
assert.match(new Date().toString(), /GMT\+0000/);
8+
9+
process.env.TZ = 'America/New_York';
10+
assert.match(new Date().toString(), /Eastern (Standard|Daylight) Time/);
11+
12+
process.env.TZ = 'America/Los_Angeles';
13+
assert.match(new Date().toString(), /Pacific (Standard|Daylight) Time/);

0 commit comments

Comments
 (0)