mirror of
https://github.com/nodejs/node.git
synced 2025-12-28 07:50:41 +00:00
lib: support setting process.env.TZ on windows
Fixes: https://github.com/nodejs/node/issues/4230 Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: https://github.com/nodejs/node/pull/38642 Reviewed-By: Steven R Loomis <srloomis@us.ibm.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
parent
75340f3c52
commit
16cb4f720b
@ -1669,6 +1669,37 @@ Be aware that unless the child environment is explicitly set, this environment
|
||||
variable will be inherited by any child processes, and if they use OpenSSL, it
|
||||
may cause them to trust the same CAs as node.
|
||||
|
||||
### `TZ`
|
||||
<!-- YAML
|
||||
added: v0.0.1
|
||||
changes:
|
||||
- version:
|
||||
- REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/38642
|
||||
description:
|
||||
Changing the TZ variable using process.env.TZ = changes the timezone
|
||||
on Windows as well.
|
||||
- version:
|
||||
- v13.0.0
|
||||
pr-url: https://github.com/nodejs/node/pull/20026
|
||||
description:
|
||||
Changing the TZ variable using process.env.TZ = changes the timezone
|
||||
on POSIX systems.
|
||||
-->
|
||||
|
||||
The `TZ` environment variable is used to specify the timezone configuration.
|
||||
|
||||
While the Node.js support for `TZ` will not handle all of the various
|
||||
[ways that `TZ` is handled in other environments][], it will support basic
|
||||
[timezone IDs][] (such as `'Etc/UTC'`, `'Europe/Paris'` or `'America/New_York'`.
|
||||
It may support a few other abbreviations or aliases, but these are strongly
|
||||
discouraged and not guaranteed.
|
||||
|
||||
```console
|
||||
$ TZ=Europe/Dublin node -pe "new Date().toString()"
|
||||
Wed May 12 2021 20:30:48 GMT+0100 (Irish Standard Time)
|
||||
```
|
||||
|
||||
### `UV_THREADPOOL_SIZE=size`
|
||||
|
||||
Set the number of threads used in libuv's threadpool to `size` threads.
|
||||
@ -1743,3 +1774,5 @@ $ node --max-old-space-size=1536 index.js
|
||||
[jitless]: https://v8.dev/blog/jitless
|
||||
[libuv threadpool documentation]: https://docs.libuv.org/en/latest/threadpool.html
|
||||
[remote code execution]: https://www.owasp.org/index.php/Code_Injection
|
||||
[timezone IDs]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
[ways that `TZ` is handled in other environments]: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
|
||||
|
||||
@ -937,6 +937,14 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
|
||||
return 9;
|
||||
}
|
||||
per_process::metadata.versions.InitializeIntlVersions();
|
||||
|
||||
# ifndef __POSIX__
|
||||
std::string tz;
|
||||
if (credentials::SafeGetenv("TZ", &tz) && !tz.empty()) {
|
||||
i18n::SetDefaultTimeZone(tz.c_str());
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
NativeModuleEnv::InitializeCodeCache();
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#include "env-inl.h"
|
||||
#include "node_errors.h"
|
||||
#include "node_external_reference.h"
|
||||
#include "node_i18n.h"
|
||||
#include "node_process.h"
|
||||
|
||||
#include <time.h> // tzset(), _tzset()
|
||||
@ -69,15 +70,32 @@ std::shared_ptr<KVStore> system_environment = std::make_shared<RealEnvStore>();
|
||||
} // namespace per_process
|
||||
|
||||
template <typename T>
|
||||
void DateTimeConfigurationChangeNotification(Isolate* isolate, const T& key) {
|
||||
void DateTimeConfigurationChangeNotification(
|
||||
Isolate* isolate,
|
||||
const T& key,
|
||||
const char* val = nullptr) {
|
||||
if (key.length() == 2 && key[0] == 'T' && key[1] == 'Z') {
|
||||
#ifdef __POSIX__
|
||||
tzset();
|
||||
isolate->DateTimeConfigurationChangeNotification(
|
||||
Isolate::TimeZoneDetection::kRedetect);
|
||||
#else
|
||||
_tzset();
|
||||
|
||||
# if defined(NODE_HAVE_I18N_SUPPORT)
|
||||
isolate->DateTimeConfigurationChangeNotification(
|
||||
Isolate::TimeZoneDetection::kSkip);
|
||||
|
||||
// On windows, the TZ environment is not supported out of the box.
|
||||
// By default, v8 will only be able to detect the system configured
|
||||
// timezone. This supports using the TZ environment variable to set
|
||||
// the default timezone instead.
|
||||
if (val != nullptr) i18n::SetDefaultTimeZone(val);
|
||||
# else
|
||||
isolate->DateTimeConfigurationChangeNotification(
|
||||
Isolate::TimeZoneDetection::kRedetect);
|
||||
# endif
|
||||
#endif
|
||||
auto constexpr time_zone_detection = Isolate::TimeZoneDetection::kRedetect;
|
||||
isolate->DateTimeConfigurationChangeNotification(time_zone_detection);
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,7 +146,7 @@ void RealEnvStore::Set(Isolate* isolate,
|
||||
if (key.length() > 0 && key[0] == '=') return;
|
||||
#endif
|
||||
uv_os_setenv(*key, *val);
|
||||
DateTimeConfigurationChangeNotification(isolate, key);
|
||||
DateTimeConfigurationChangeNotification(isolate, key, *val);
|
||||
}
|
||||
|
||||
int32_t RealEnvStore::Query(const char* key) const {
|
||||
|
||||
@ -542,6 +542,16 @@ bool InitializeICUDirectory(const std::string& path) {
|
||||
return status == U_ZERO_ERROR;
|
||||
}
|
||||
|
||||
void SetDefaultTimeZone(const char* tzid) {
|
||||
size_t tzidlen = strlen(tzid) + 1;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
MaybeStackBuffer<UChar, 256> id(tzidlen);
|
||||
u_charsToUChars(tzid, id.out(), tzidlen);
|
||||
// This is threadsafe:
|
||||
ucal_setDefaultTimeZone(id.out(), &status);
|
||||
CHECK(U_SUCCESS(status));
|
||||
}
|
||||
|
||||
int32_t ToUnicode(MaybeStackBuffer<char>* buf,
|
||||
const char* input,
|
||||
size_t length) {
|
||||
|
||||
@ -40,6 +40,8 @@ namespace i18n {
|
||||
|
||||
bool InitializeICUDirectory(const std::string& path);
|
||||
|
||||
void SetDefaultTimeZone(const char* tzid);
|
||||
|
||||
enum idna_mode {
|
||||
// Default mode for maximum compatibility.
|
||||
IDNA_DEFAULT,
|
||||
|
||||
24
test/parallel/test-datetime-change-notify.js
Normal file
24
test/parallel/test-datetime-change-notify.js
Normal file
@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const { isMainThread } = require('worker_threads');
|
||||
|
||||
if (!common.hasIntl)
|
||||
common.skip('Intl not present.');
|
||||
|
||||
if (!isMainThread)
|
||||
common.skip('Test not support running within a worker');
|
||||
|
||||
const assert = require('assert');
|
||||
|
||||
process.env.TZ = 'Etc/UTC';
|
||||
assert.match(new Date().toString(), /GMT\+0000/);
|
||||
|
||||
process.env.TZ = 'America/New_York';
|
||||
assert.match(new Date().toString(), /Eastern (Standard|Daylight) Time/);
|
||||
|
||||
process.env.TZ = 'America/Los_Angeles';
|
||||
assert.match(new Date().toString(), /Pacific (Standard|Daylight) Time/);
|
||||
|
||||
process.env.TZ = 'Europe/Dublin';
|
||||
assert.match(new Date().toString(), /Irish/);
|
||||
Loading…
Reference in New Issue
Block a user