From 5fed4a56b2c0d1b50004187486d9c47e1bdf45a0 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 18 Sep 2018 20:51:30 +0000 Subject: [PATCH] Bug 1491159 - More complete handling of TZ environment variable when initializing ICU timezone. r=anba This improves on the changes in bug 1484829 by handling the absolute filename form of TZ environment variables both with and without an initial ':' character, and by improving comments about relative and absolute paths. (Note that relative paths without the ':' are just Olson time zone names.) Note that the only test that failed without the patch was: setTimeZone("/usr/share/zoneinfo/America/Chicago"); assertEq(timeZoneName(), "Central Daylight Time"); and it reported Error: Assertion failed: got "GMT-06:00", expected "Central Daylight Time" which seems to be a sign that ICU gets some information out of that time zone identifier (i.e., it reported the correct standard-time GMT offset), but not everything. Differential Revision: https://phabricator.services.mozilla.com/D5827 --HG-- rename : js/src/tests/non262/Date/time-zone-etc_localetime.js => js/src/tests/non262/Date/time-zone-path.js extra : moz-landing-system : lando --- js/src/tests/non262/Date/time-zone-path.js | 30 ++++++++++++++++++++++ js/src/vm/DateTime.cpp | 25 +++++++++++------- 2 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 js/src/tests/non262/Date/time-zone-path.js diff --git a/js/src/tests/non262/Date/time-zone-path.js b/js/src/tests/non262/Date/time-zone-path.js new file mode 100644 index 000000000000..3422022e2be4 --- /dev/null +++ b/js/src/tests/non262/Date/time-zone-path.js @@ -0,0 +1,30 @@ +// |reftest| skip-if(xulRuntime.OS=="WINNT"||!xulRuntime.shell) + +assertEq(/^(PST|PDT)$/.test(getTimeZone()), true, + "The default time zone is set to PST8PDT for all jstests (when run in the shell)"); + +function timeZoneName() { + var dtf = new Intl.DateTimeFormat("en-US", {timeZoneName: "long"}); + return dtf.formatToParts(Date.UTC(2017, 2, 31, 12, 0, 0)).filter(x => x.type === "timeZoneName")[0].value; +} + +setTimeZone("Europe/Paris"); +assertEq(timeZoneName(), "Central European Summer Time"); + +setTimeZone(":Europe/Helsinki"); +assertEq(timeZoneName(), "Eastern European Summer Time"); + +setTimeZone("::Europe/London"); // two colons, invalid +assertEq(timeZoneName(), "Coordinated Universal Time"); + +setTimeZone("/this-part-is-ignored/zoneinfo/America/Chicago"); +assertEq(timeZoneName(), "Central Daylight Time"); + +setTimeZone(":/this-part-is-ignored/zoneinfo/America/Phoenix"); +assertEq(timeZoneName(), "Mountain Standard Time"); + +setTimeZone("::/this-part-is-ignored/zoneinfo/America/Los_Angeles"); // two colons, invalid +assertEq(timeZoneName(), "Coordinated Universal Time"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/vm/DateTime.cpp b/js/src/vm/DateTime.cpp index a4ad3faa7011..f5079920ae54 100644 --- a/js/src/vm/DateTime.cpp +++ b/js/src/vm/DateTime.cpp @@ -626,13 +626,17 @@ IsOlsonCompatibleWindowsTimeZoneId(const char* tz) } #elif ENABLE_INTL_API && defined(ICU_TZ_HAS_RECREATE_DEFAULT) static inline const char* -TZContainsPath(const char* tzVar) +TZContainsAbsolutePath(const char* tzVar) { - // A TZ beginning with a colon is expected to be followed by a path -- - // typically an absolute path (often /etc/localtime), but alternatively a - // path relative to /usr/share/zoneinfo/. - // NB: We currently only support absolute paths. - return tzVar[0] == ':' && tzVar[1] == '/' ? tzVar + 1 : nullptr; + // A TZ environment variable may be an absolute path. The path + // format of TZ may begin with a colon. (ICU handles relative paths.) + if (tzVar[0] == ':' && tzVar[1] == '/') { + return tzVar + 1; + } + if (tzVar[0] == '/') { + return tzVar; + } + return nullptr; } /** @@ -777,10 +781,13 @@ js::ResyncICUDefaultTimeZone() // TODO: Handle invalid time zone identifiers (bug 342068). } #else - // Handle links (starting with ':') manually because ICU currently - // doesn't support the TZ filespec format. + // The TZ environment variable allows both absolute and + // relative paths, optionally beginning with a colon (':'). + // (Relative paths, without the colon, are just Olson time + // zone names.) We need to handle absolute paths ourselves, + // including handling that they might be symlinks. // - if (const char* tzlink = TZContainsPath(tz)) + if (const char* tzlink = TZContainsAbsolutePath(tz)) tzid.setTo(ReadTimeZoneLink(tzlink)); #endif /* defined(XP_WIN) */