From 05e54e1f0109a1c8098d9b97d1c6ef77b7f62cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Fri, 29 Nov 2024 12:23:35 +0000 Subject: [PATCH] Bug 1930466 - Part 1: Use zone.tab to guide time zone canonicalisation. r=dminor Implement the changes from to reduce differences in time zone canonicalisation when compared to V8 and JSC (which both use CLDR time zone data instead of IANA time zone data). Implementing the `AvailableNamedTimeZoneIdentifiers` spec operation requires to link time zone identifiers to region codes. When the time zone is listed in the "zone.tab" file, we can get the region code from "zone.tab". In all other cases we need to manually map the time zone to a matching region, because CLDR doesn't have "public" data for this [1]. This is implemented using the new file "intl/TimeZoneMapping.yaml". ICU 74 added `ucal_getIanaTimeZoneID` to get the canonical IANA time zone id. Internally `ucal_getIanaTimeZoneID` first calls `ucal_getCanonicalTimeZoneID` and then loads a resource bundle to check if there are any time zone ids which need to be replaced with other ids for compatibility with IANA data. Unfortunately the resource bundle is not cached, so calling `ucal_getIanaTimeZoneID` instead of `ucal_getIanaTimeZoneID` adds a considerable performance overhead. To avoid any performance regressions, we keep our own time zone rewriting code for the time being. Using our own code also means we don't have to add a workaround for this CLDR bug: . Also remove "Factory" from the list of supported time zone identifiers, because supporting it was always a bit questionable and latest V8 also doesn't support it anymore, so we shouldn't run into web-compat issues. Remove the old generated tests and add "timeZone_links.js" to ensure time zone links are correctly resolved. [1] Neither of these two files look like "public" data to me: - https://github.com/unicode-org/cldr/blob/main/tools/cldr-code/src/main/resources/org/unicode/cldr/util/data/TZID.txt - https://github.com/unicode-org/cldr/blob/main/tools/cldr-code/src/main/resources/org/unicode/cldr/icu/idList.txt Differential Revision: https://phabricator.services.mozilla.com/D228584 --- .../test/browser/browser_timezone.js | 12 +- js/src/builtin/intl/TimeZoneDataGenerated.h | 78 ++-- js/src/builtin/intl/TimeZoneMapping.yaml | 157 +++++++ js/src/builtin/intl/make_intl_data.py | 413 ++++++++---------- .../tests/resist-fingerprinting/timezone.js | 2 +- .../Intl/DateTimeFormat/timeZone_backzone.js | 163 ------- .../DateTimeFormat/timeZone_backzone_links.js | 48 -- ...ne_backward_links.js => timeZone_links.js} | 81 ++-- .../timeZone_notbackward_links.js | 31 -- .../DateTimeFormat/tz-environment-variable.js | 8 +- .../supportedValuesOf-timeZones-canonical.js | 50 +-- 11 files changed, 442 insertions(+), 601 deletions(-) create mode 100644 js/src/builtin/intl/TimeZoneMapping.yaml delete mode 100644 js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js delete mode 100644 js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js rename js/src/tests/non262/Intl/DateTimeFormat/{timeZone_backward_links.js => timeZone_links.js} (72%) delete mode 100644 js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js diff --git a/browser/components/resistfingerprinting/test/browser/browser_timezone.js b/browser/components/resistfingerprinting/test/browser/browser_timezone.js index e4ae654c579be..2cd284da8e02f 100644 --- a/browser/components/resistfingerprinting/test/browser/browser_timezone.js +++ b/browser/components/resistfingerprinting/test/browser/browser_timezone.js @@ -10,7 +10,7 @@ async function verifySpoofed() { SpecialPowers.Cu.getJSTestingFunctions().setTimeZone("PST8PDT"); is( Intl.DateTimeFormat("en-US").resolvedOptions().timeZone, - "PST8PDT", + "America/Los_Angeles", "Default time zone should have changed" ); @@ -116,7 +116,7 @@ add_task(async function test_timezone_exempt() { SpecialPowers.Cu.getJSTestingFunctions().setTimeZone("PST8PDT"); is( Intl.DateTimeFormat("en-US").resolvedOptions().timeZone, - "PST8PDT", + "America/Los_Angeles", "Default time zone should have changed" ); @@ -129,7 +129,7 @@ add_task(async function test_timezone_exempt() { is( Intl.DateTimeFormat("en-US").resolvedOptions().timeZone, - "PST8PDT", + "America/Los_Angeles", "Content should use default time zone" ); } @@ -172,7 +172,7 @@ add_task(async function test_timezone_exmpt_browser() { SpecialPowers.Cu.getJSTestingFunctions().setTimeZone("PST8PDT"); is( Intl.DateTimeFormat("en-US").resolvedOptions().timeZone, - "PST8PDT", + "America/Los_Angeles", "Default time zone should have changed" ); @@ -182,7 +182,7 @@ add_task(async function test_timezone_exmpt_browser() { is( Intl.DateTimeFormat("en-US").resolvedOptions().timeZone, - "PST8PDT", + "America/Los_Angeles", "Timezone in chrome should be unaffected by resistFingerprinting" ); @@ -196,7 +196,7 @@ add_task(async function test_timezone_exmpt_browser() { is( newWindow.Intl.DateTimeFormat("en-US").resolvedOptions().timeZone, - "PST8PDT", + "America/Los_Angeles", "Timezone in new chrome window should be unaffected by resistFingerprinting" ); diff --git a/js/src/builtin/intl/TimeZoneDataGenerated.h b/js/src/builtin/intl/TimeZoneDataGenerated.h index 04113afa1c86d..ae366e9b2d7ea 100644 --- a/js/src/builtin/intl/TimeZoneDataGenerated.h +++ b/js/src/builtin/intl/TimeZoneDataGenerated.h @@ -10,58 +10,26 @@ namespace timezone { // Format: // "ZoneName" // ICU-Name [time zone file] const char* const ianaZonesTreatedAsLinksByICU[] = { - "Africa/Asmara", // Africa/Asmera [backzone] - "Africa/Timbuktu", // Africa/Bamako [backzone] + "Africa/Asmara", // Africa/Asmera [backward] "America/Argentina/Buenos_Aires", // America/Buenos_Aires [southamerica] "America/Argentina/Catamarca", // America/Catamarca [southamerica] - "America/Argentina/ComodRivadavia", // America/Catamarca [backzone] "America/Argentina/Cordoba", // America/Cordoba [southamerica] "America/Argentina/Jujuy", // America/Jujuy [southamerica] "America/Argentina/Mendoza", // America/Mendoza [southamerica] - "America/Atikokan", // America/Coral_Harbour [backzone] - "America/Ensenada", // America/Tijuana [backzone] + "America/Atikokan", // America/Coral_Harbour [backward] "America/Indiana/Indianapolis", // America/Indianapolis [northamerica] "America/Kentucky/Louisville", // America/Louisville [northamerica] - "America/Montreal", // America/Toronto [backzone] - "America/Nipigon", // America/Toronto [backzone] "America/Nuuk", // America/Godthab [europe] - "America/Pangnirtung", // America/Iqaluit [backzone] - "America/Rainy_River", // America/Winnipeg [backzone] - "America/Rosario", // America/Cordoba [backzone] - "America/Thunder_Bay", // America/Toronto [backzone] - "America/Yellowknife", // America/Edmonton [backzone] - "Asia/Chongqing", // Asia/Shanghai [backzone] - "Asia/Harbin", // Asia/Shanghai [backzone] "Asia/Ho_Chi_Minh", // Asia/Saigon [asia] - "Asia/Kashgar", // Asia/Urumqi [backzone] "Asia/Kathmandu", // Asia/Katmandu [asia] "Asia/Kolkata", // Asia/Calcutta [asia] - "Asia/Tel_Aviv", // Asia/Jerusalem [backzone] "Asia/Yangon", // Asia/Rangoon [asia] "Atlantic/Faroe", // Atlantic/Faeroe [europe] - "Atlantic/Jan_Mayen", // Arctic/Longyearbyen [backzone] - "Australia/Currie", // Australia/Hobart [backzone] - "CET", // Europe/Brussels [backzone] - "CST6CDT", // America/Chicago [backzone] - "EET", // Europe/Athens [backzone] - "EST", // America/Panama [backzone] - "EST5EDT", // America/New_York [backzone] - "Europe/Belfast", // Europe/London [backzone] "Europe/Kyiv", // Europe/Kiev [europe] - "Europe/Tiraspol", // Europe/Chisinau [backzone] - "Europe/Uzhgorod", // Europe/Kiev [backzone] - "Europe/Zaporozhye", // Europe/Kiev [backzone] - "Factory", // Etc/Unknown [factory] - "HST", // Pacific/Honolulu [backzone] - "MET", // Europe/Brussels [backzone] - "MST", // America/Phoenix [backzone] - "MST7MDT", // America/Denver [backzone] - "PST8PDT", // America/Los_Angeles [backzone] - "Pacific/Chuuk", // Pacific/Truk [backzone] - "Pacific/Johnston", // Pacific/Honolulu [backzone] + "Pacific/Chuuk", // Pacific/Truk [backward] "Pacific/Kanton", // Pacific/Enderbury [australasia] - "Pacific/Pohnpei", // Pacific/Ponape [backzone] - "WET", // Europe/Lisbon [backzone] + "Pacific/Pohnpei", // Pacific/Ponape [backward] + "UTC", // Etc/UTC [backward] }; // Format: @@ -74,38 +42,49 @@ struct LinkAndTarget const LinkAndTarget ianaLinksCanonicalizedDifferentlyByICU[] = { { "Africa/Asmera", "Africa/Asmara" }, // Africa/Asmera [backward] + { "America/Argentina/ComodRivadavia", "America/Argentina/Catamarca" }, // America/Catamarca [backward] { "America/Buenos_Aires", "America/Argentina/Buenos_Aires" }, // America/Buenos_Aires [backward] { "America/Catamarca", "America/Argentina/Catamarca" }, // America/Catamarca [backward] + { "America/Coral_Harbour", "America/Atikokan" }, // America/Coral_Harbour [backward] { "America/Cordoba", "America/Argentina/Cordoba" }, // America/Cordoba [backward] { "America/Fort_Wayne", "America/Indiana/Indianapolis" }, // America/Indianapolis [backward] { "America/Godthab", "America/Nuuk" }, // America/Godthab [backward] { "America/Indianapolis", "America/Indiana/Indianapolis" }, // America/Indianapolis [backward] { "America/Jujuy", "America/Argentina/Jujuy" }, // America/Jujuy [backward] - { "America/Kralendijk", "America/Curacao" }, // America/Kralendijk [backward] { "America/Louisville", "America/Kentucky/Louisville" }, // America/Louisville [backward] - { "America/Lower_Princes", "America/Curacao" }, // America/Lower_Princes [backward] - { "America/Marigot", "America/Port_of_Spain" }, // America/Marigot [backward] { "America/Mendoza", "America/Argentina/Mendoza" }, // America/Mendoza [backward] - { "America/St_Barthelemy", "America/Port_of_Spain" }, // America/St_Barthelemy [backward] + { "America/Rosario", "America/Argentina/Cordoba" }, // America/Cordoba [backward] { "Antarctica/South_Pole", "Antarctica/McMurdo" }, // Pacific/Auckland [backward] - { "Arctic/Longyearbyen", "Europe/Oslo" }, // Arctic/Longyearbyen [backward] { "Asia/Calcutta", "Asia/Kolkata" }, // Asia/Calcutta [backward] - { "Asia/Chungking", "Asia/Chongqing" }, // Asia/Shanghai [backward] { "Asia/Katmandu", "Asia/Kathmandu" }, // Asia/Katmandu [backward] { "Asia/Rangoon", "Asia/Yangon" }, // Asia/Rangoon [backward] { "Asia/Saigon", "Asia/Ho_Chi_Minh" }, // Asia/Saigon [backward] { "Atlantic/Faeroe", "Atlantic/Faroe" }, // Atlantic/Faeroe [backward] - { "Europe/Bratislava", "Europe/Prague" }, // Europe/Bratislava [backward] - { "Europe/Busingen", "Europe/Zurich" }, // Europe/Busingen [backward] + { "Etc/GMT", "UTC" }, // Etc/GMT [etcetera] + { "Etc/GMT+0", "UTC" }, // Etc/GMT [backward] + { "Etc/GMT-0", "UTC" }, // Etc/GMT [backward] + { "Etc/GMT0", "UTC" }, // Etc/GMT [backward] + { "Etc/Greenwich", "UTC" }, // Etc/GMT [backward] + { "Etc/UCT", "UTC" }, // Etc/UTC [backward] + { "Etc/UTC", "UTC" }, // Etc/UTC [etcetera] + { "Etc/Universal", "UTC" }, // Etc/UTC [backward] + { "Etc/Zulu", "UTC" }, // Etc/UTC [backward] { "Europe/Kiev", "Europe/Kyiv" }, // Europe/Kiev [backward] - { "Europe/Mariehamn", "Europe/Helsinki" }, // Europe/Mariehamn [backward] - { "Europe/Podgorica", "Europe/Belgrade" }, // Europe/Podgorica [backward] - { "Europe/San_Marino", "Europe/Rome" }, // Europe/San_Marino [backward] - { "Europe/Vatican", "Europe/Rome" }, // Europe/Vatican [backward] + { "Europe/Uzhgorod", "Europe/Kyiv" }, // Europe/Kiev [backward] + { "Europe/Zaporozhye", "Europe/Kyiv" }, // Europe/Kiev [backward] + { "GMT", "UTC" }, // Etc/GMT [etcetera] + { "GMT+0", "UTC" }, // Etc/GMT [backward] + { "GMT-0", "UTC" }, // Etc/GMT [backward] + { "GMT0", "UTC" }, // Etc/GMT [backward] + { "Greenwich", "UTC" }, // Etc/GMT [backward] + { "Pacific/Enderbury", "Pacific/Kanton" }, // Pacific/Enderbury [backward] { "Pacific/Ponape", "Pacific/Pohnpei" }, // Pacific/Ponape [backward] { "Pacific/Truk", "Pacific/Chuuk" }, // Pacific/Truk [backward] { "Pacific/Yap", "Pacific/Chuuk" }, // Pacific/Truk [backward] + { "UCT", "UTC" }, // Etc/UTC [backward] { "US/East-Indiana", "America/Indiana/Indianapolis" }, // America/Indianapolis [backward] + { "Universal", "UTC" }, // Etc/UTC [backward] + { "Zulu", "UTC" }, // Etc/UTC [backward] }; // Legacy ICU time zones, these are not valid IANA time zone names. We also @@ -139,6 +118,7 @@ const char* const legacyICUTimeZones[] = { "SST", "US/Pacific-New", "VST", + "Factory", "SystemV/AST4", "SystemV/AST4ADT", "SystemV/CST6", diff --git a/js/src/builtin/intl/TimeZoneMapping.yaml b/js/src/builtin/intl/TimeZoneMapping.yaml new file mode 100644 index 0000000000000..1ddccccb5b12a --- /dev/null +++ b/js/src/builtin/intl/TimeZoneMapping.yaml @@ -0,0 +1,157 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Provide mapping from time zone identifiers to region codes for time zones +# which aren't listed in tzdata's zone.tab file. + +Africa/Timbuktu: ML +Africa/Asmera: ER + +America/Argentina/ComodRivadavia: AR +America/Atka: US +America/Buenos_Aires: AR +America/Catamarca: AR +America/Coral_Harbour: CA +America/Cordoba: AR +America/Ensenada: MX +America/Fort_Wayne: US +America/Godthab: GL +America/Indianapolis: US +America/Jujuy: AR +America/Knox_IN: US +America/Louisville: US +America/Mendoza: AR +America/Montreal: CA +America/Nipigon: CA +America/Pangnirtung: CA +America/Porto_Acre: BR +America/Rainy_River: CA +America/Rosario: AR +America/Santa_Isabel: MX +America/Shiprock: US +America/Thunder_Bay: CA +America/Virgin: VI +America/Yellowknife: CA + +Antarctica/South_Pole: AQ + +Asia/Choibalsan: MN +Asia/Chongqing: CN +Asia/Harbin: CN +Asia/Kashgar: CN +Asia/Tel_Aviv: IL +Asia/Ashkhabad: TM +Asia/Calcutta: IN +Asia/Chungking: CN +Asia/Dacca: BD +Asia/Istanbul: TR +Asia/Katmandu: NP +Asia/Macao: MO +Asia/Rangoon: MM +Asia/Saigon: VN +Asia/Thimbu: BT +Asia/Ujung_Pandang: ID +Asia/Ulan_Bator: MN + +Atlantic/Jan_Mayen: SJ +Atlantic/Faeroe: FO + +Australia/ACT: AU +Australia/LHI: AU +Australia/NSW: AU +Australia/Canberra: AU +Australia/Currie: AU +Australia/North: AU +Australia/Queensland: AU +Australia/South: AU +Australia/Tasmania: AU +Australia/Victoria: AU +Australia/West: AU +Australia/Yancowinna: AU + +Europe/Belfast: GB +Europe/Tiraspol: MD +Europe/Uzhgorod: UA +Europe/Zaporozhye: UA +Europe/Kiev: UA +Europe/Nicosia: CY + +Pacific/Samoa: AS +Pacific/Enderbury: KI +Pacific/Johnston: US +Pacific/Yap: FM +Pacific/Ponape: FM +Pacific/Truk: FM + +Brazil/Acre: BR +Brazil/DeNoronha: BR +Brazil/East: BR +Brazil/West: BR + +Canada/Atlantic: CA +Canada/Central: CA +Canada/Eastern: CA +Canada/Mountain: CA +Canada/Newfoundland: CA +Canada/Pacific: CA +Canada/Saskatchewan: CA +Canada/Yukon: CA + +Chile/Continental: CL +Chile/EasterIsland: CL + +Mexico/BajaNorte: MX +Mexico/BajaSur: MX +Mexico/General: MX + +US/Alaska: US +US/Aleutian: US +US/Arizona: US +US/Central: US +US/East-Indiana: US +US/Eastern: US +US/Hawaii: US +US/Indiana-Starke: US +US/Michigan: US +US/Mountain: US +US/Pacific: US +US/Samoa: AS + +CET: BE +EET: GR +MET: BE +WET: PT + +CST6CDT: US +EST5EDT: US +EST: PA +HST: US +MST7MDT: US +MST: US +PST8PDT: US + +Cuba: CU +Egypt: EG +Eire: IE +GB: GB +GB-Eire: GB +Hongkong: HK +Iceland: IS +Iran: IR +Israel: IL +Jamaica: JM +Japan: JP +Kwajalein: MH +Libya: LY +NZ: NZ +NZ-CHAT: NZ +Navajo: US +PRC: CN +Poland: PL +Portugal: PT +ROC: TW +ROK: KR +Singapore: SG +Turkey: TR +W-SU: RU diff --git a/js/src/builtin/intl/make_intl_data.py b/js/src/builtin/intl/make_intl_data.py index a37f7d6d5b7ad..c757940631007 100755 --- a/js/src/builtin/intl/make_intl_data.py +++ b/js/src/builtin/intl/make_intl_data.py @@ -45,32 +45,19 @@ import json import os import re -import sys import tarfile import tempfile from contextlib import closing from functools import partial, total_ordering -from itertools import chain, groupby, tee +from itertools import chain, filterfalse, groupby, tee, zip_longest from operator import attrgetter, itemgetter +from urllib.parse import urlsplit +from urllib.request import Request as UrlRequest +from urllib.request import urlopen from zipfile import ZipFile import yaml -if sys.version_info.major == 2: - from itertools import ifilter as filter - from itertools import ifilterfalse as filterfalse - from itertools import imap as map - from itertools import izip_longest as zip_longest - - from urllib2 import Request as UrlRequest - from urllib2 import urlopen - from urlparse import urlsplit -else: - from itertools import filterfalse, zip_longest - from urllib.parse import urlsplit - from urllib.request import Request as UrlRequest - from urllib.request import urlopen - # From https://docs.python.org/3/library/itertools.html def grouper(iterable, n, fillvalue=None): @@ -2215,7 +2202,8 @@ def readIANAFiles(tzdataDir, files): nameSyntax = r"[\w/+\-]+" pZone = re.compile(r"Zone\s+(?P%s)\s+.*" % nameSyntax) pLink = re.compile( - r"Link\s+(?P%s)\s+(?P%s)(?:\s+#.*)?" % (nameSyntax, nameSyntax) + r"(#PACKRATLIST\s+zone.tab\s+)?Link\s+(?P%s)\s+(?P%s)(?:\s+#.*)?" + % (nameSyntax, nameSyntax) ) def createZone(line, fname): @@ -2230,6 +2218,7 @@ def createLink(line, fname): zones = set() links = dict() + packrat_links = dict() for filename in files: filepath = tzdataDir.resolve(filename) for line in tzdataDir.readlines(filepath): @@ -2238,31 +2227,26 @@ def createLink(line, fname): if line.startswith("Link"): (link, target) = createLink(line, filename) links[link] = target + if line.startswith("#PACKRATLIST zone.tab Link"): + (link, target) = createLink(line, filename) + packrat_links[link] = target - return (zones, links) + return (zones, links, packrat_links) -def readIANATimeZones(tzdataDir, ignoreBackzone, ignoreFactory): +def readIANATimeZones(tzdataDir, ignoreFactory): """Read the IANA time zone information from `tzdataDir`.""" - backzoneFiles = {"backzone"} - (bkfiles, tzfiles) = partition(listIANAFiles(tzdataDir), backzoneFiles.__contains__) + files_to_ignore = ["backzone"] - # Read zone and link infos. - (zones, links) = readIANAFiles(tzdataDir, tzfiles) - (backzones, backlinks) = readIANAFiles(tzdataDir, bkfiles) - - # Remove the placeholder time zone "Factory". + # Ignore the placeholder time zone "Factory". if ignoreFactory: - zones.remove(Zone("Factory")) + files_to_ignore.append("factory") - # Merge with backzone data. - if not ignoreBackzone: - zones |= backzones - links = { - name: target for name, target in links.items() if name not in backzones - } - links.update(backlinks) + tzfiles = (file for file in listIANAFiles(tzdataDir) if file not in files_to_ignore) + + # Read zone and link infos. + (zones, links, _) = readIANAFiles(tzdataDir, tzfiles) validateTimeZones(zones, links) @@ -2431,7 +2415,13 @@ def readICUTimeZones(icuDir, icuTzDir, ignoreFactory): # Remove the placeholder time zone "Factory". # See also . if ignoreFactory: + assert Zone("Factory") in zoneinfoZones + assert Zone("Factory") not in zoneinfoLinks + assert Zone("Factory") not in typesZones + assert Zone("Factory") in typesLinks + zoneinfoZones.remove(Zone("Factory")) + del typesLinks[Zone("Factory")] # Remove the ICU placeholder time zone "Etc/Unknown". # See also . @@ -2497,7 +2487,7 @@ def readICULegacyZones(icuDir): # non-IANA time zones and links. # Most legacy, non-IANA time zones and links are in the icuzones file. - (zones, links) = readIANAFiles(tzdir, ["icuzones"]) + (zones, links, _) = readIANAFiles(tzdir, ["icuzones"]) # Remove the ICU placeholder time zone "Etc/Unknown". # See also . @@ -2561,7 +2551,7 @@ def searchInFile(pattern, f): return version -def findIncorrectICUZones(ianaZones, ianaLinks, icuZones, icuLinks, ignoreBackzone): +def findIncorrectICUZones(ianaZones, ianaLinks, icuZones, icuLinks): """Find incorrect ICU zone entries.""" def isIANATimeZone(zone): @@ -2575,11 +2565,7 @@ def isICULink(zone): # All IANA zones should be present in ICU. missingTimeZones = [zone for zone in ianaZones if not isICUTimeZone(zone)] - # Normally zones in backzone are also present as links in one of the other - # time zone files. The only exception to this rule is the Asia/Hanoi time - # zone, this zone is only present in the backzone file. - expectedMissing = [] if ignoreBackzone else [Zone("Asia/Hanoi")] - if missingTimeZones != expectedMissing: + if missingTimeZones: raise RuntimeError( "Not all zones are present in ICU, did you forget " "to run intl/update-tzdata.sh? %s" % missingTimeZones @@ -2660,28 +2646,157 @@ def isICUZone(zone): return sorted(result, key=itemgetter(0)) +def readZoneTab(tzdataDir): + zone_country = dict() + + zonetab_path = tzdataDir.resolve("zone.tab") + for line in tzdataDir.readlines(zonetab_path): + if line.startswith("#"): + continue + (country, coords, zone, *comments) = line.strip().split("\t") + assert zone not in zone_country + zone_country[zone] = country + + return zone_country + + +# 6.5.1 AvailableNamedTimeZoneIdentifiers ( ) +# +# https://tc39.es/ecma402/#sup-availablenamedtimezoneidentifiers +def availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory): + js_src_builtin_intl_dir = os.path.dirname(os.path.abspath(__file__)) + + with io.open( + os.path.join(js_src_builtin_intl_dir, "TimeZoneMapping.yaml"), + mode="r", + encoding="utf-8", + ) as f: + time_zone_mapping = yaml.safe_load(f) + + zone_country = readZoneTab(tzdataDir) + + def country_code_for(name): + if name in zone_country: + return zone_country[name] + return time_zone_mapping[name] + + (ianaZones, ianaLinks) = readIANATimeZones(tzdataDir, ignoreFactory) + + (backzones, backlinks, packratlinks) = readIANAFiles(tzdataDir, ["backzone"]) + all_backzone_links = {**backlinks, **packratlinks} + + # Steps 1-3. (Not applicable) + + # Step 4. + zones = set() + links = dict() + + # Step 5. (Partial, only zones) + for zone in ianaZones: + # Step 5.a. + primary = zone + + # Step 5.b. (Not applicable for zones) + + # Step 5.c. + if primary.name in ["Etc/UTC", "Etc/GMT", "GMT"]: + primary = Zone("UTC", primary.filename) + + # Step 5.d. (Not applicable) + + # Steps 5.e-f. + if primary == zone: + assert zone not in zones + zones.add(primary) + else: + assert zone not in links + links[zone] = primary.name + + # Step 5. (Partial, only links) + for zone, target in ianaLinks.items(): + identifier = zone.name + + # Step 5.a. + primary = identifier + + # Step 5.b. + if identifier not in zone_country: + # Step 5.b.i. (Not applicable) + + # Steps 5.b.ii-iii. + if target.startswith("Etc/"): + primary = target + else: + # Step 5.b.iii.1. + identifier_code_code = country_code_for(identifier) + + # Step 5.b.iii.2. + target_code_code = country_code_for(target) + + # Steps 5.b.iii.3-4 + if identifier_code_code == target_code_code: + primary = target + else: + # Step 5.b.iii.4.a. + country_code_line_count = [ + zone + for (zone, code) in zone_country.items() + if code == identifier_code_code + ] + + # Steps 5.b.iii.4.b-c. + if len(country_code_line_count) == 1: + primary = country_code_line_count[0] + else: + assert Zone(identifier) in all_backzone_links + primary = all_backzone_links[Zone(identifier)] + assert identifier_code_code == country_code_for(primary) + + # Step 5.c. + if primary in ["Etc/UTC", "Etc/GMT", "GMT"]: + primary = "UTC" + + # Step 5.d. (Not applicable) + + # Steps 5.e-f. + if primary == identifier: + assert zone not in zones + zones.add(zone) + else: + assert zone not in links + links[zone] = primary + + # Ensure all zones and links are valid. + validateTimeZones(zones, links) + + # Step 6. + assert Zone("UTC") in zones + + # Step 7. + return (zones, links) + + generatedFileWarning = "// Generated by make_intl_data.py. DO NOT EDIT." tzdataVersionComment = "// tzdata version = {0}" -def processTimeZones( - tzdataDir, icuDir, icuTzDir, version, ignoreBackzone, ignoreFactory, out -): +def processTimeZones(tzdataDir, icuDir, icuTzDir, version, ignoreFactory, out): """Read the time zone info and create a new time zone cpp file.""" print("Processing tzdata mapping...") - (ianaZones, ianaLinks) = readIANATimeZones(tzdataDir, ignoreBackzone, ignoreFactory) + (ianaZones, ianaLinks) = availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory) (icuZones, icuLinks) = readICUTimeZones(icuDir, icuTzDir, ignoreFactory) (legacyZones, legacyLinks) = readICULegacyZones(icuDir) + if ignoreFactory: + legacyZones.add(Zone("Factory")) + # Remove all legacy ICU time zones. icuZones = {zone for zone in icuZones if zone not in legacyZones} icuLinks = { zone: target for (zone, target) in icuLinks.items() if zone not in legacyLinks } - incorrectZones = findIncorrectICUZones( - ianaZones, ianaLinks, icuZones, icuLinks, ignoreBackzone - ) + incorrectZones = findIncorrectICUZones(ianaZones, ianaLinks, icuZones, icuLinks) if not incorrectZones: print("<<< No incorrect ICU time zones found, please update Intl.js! >>>") print("<<< Maybe https://ssl.icu-project.org/trac/ticket/12044 was fixed? >>>") @@ -2751,28 +2866,12 @@ def processTimeZones( println("#endif /* builtin_intl_TimeZoneDataGenerated_h */") -def updateBackzoneLinks(tzdataDir, links): - def withZone(fn): - return lambda zone_target: fn(zone_target[0]) - - (backzoneZones, backzoneLinks) = readIANAFiles(tzdataDir, ["backzone"]) - (stableZones, updatedLinks, updatedZones) = partition( - links.items(), - # Link not changed in backzone. - withZone(lambda zone: zone not in backzoneLinks and zone not in backzoneZones), - # Link has a new target. - withZone(lambda zone: zone in backzoneLinks), - ) - # Keep stable zones and links with updated target. - return dict( - chain( - stableZones, - map(withZone(lambda zone: (zone, backzoneLinks[zone])), updatedLinks), - ) - ) +def generateTzDataTestLinks(tzdataDir, version, ignoreFactory, testDir): + fileName = "timeZone_links.js" + # Read zone and link infos. + (_, links) = availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory) -def generateTzDataLinkTestContent(testDir, version, fileName, description, links): with io.open( os.path.join(testDir, fileName), mode="w", encoding="utf-8", newline="" ) as f: @@ -2792,9 +2891,9 @@ def generateTzDataLinkTestContent(testDir, version, fileName, description, links """ ) - println(description) + println("// Link names derived from IANA Time Zone Database.") println("const links = {") - for zone, target in sorted(links, key=itemgetter(0)): + for zone, target in sorted(links.items(), key=itemgetter(0)): println(' "%s": "%s",' % (zone, target)) println("};") @@ -2820,112 +2919,6 @@ def generateTzDataLinkTestContent(testDir, version, fileName, description, links ) -def generateTzDataTestBackwardLinks(tzdataDir, version, ignoreBackzone, testDir): - (zones, links) = readIANAFiles(tzdataDir, ["backward"]) - assert len(zones) == 0 - - if not ignoreBackzone: - links = updateBackzoneLinks(tzdataDir, links) - - generateTzDataLinkTestContent( - testDir, - version, - "timeZone_backward_links.js", - "// Link names derived from IANA Time Zone Database, backward file.", - links.items(), - ) - - -def generateTzDataTestNotBackwardLinks(tzdataDir, version, ignoreBackzone, testDir): - tzfiles = filterfalse( - {"backward", "backzone"}.__contains__, listIANAFiles(tzdataDir) - ) - (zones, links) = readIANAFiles(tzdataDir, tzfiles) - - if not ignoreBackzone: - links = updateBackzoneLinks(tzdataDir, links) - - generateTzDataLinkTestContent( - testDir, - version, - "timeZone_notbackward_links.js", - "// Link names derived from IANA Time Zone Database, excluding backward file.", - links.items(), - ) - - -def generateTzDataTestBackzone(tzdataDir, version, ignoreBackzone, testDir): - backzoneFiles = {"backzone"} - (bkfiles, tzfiles) = partition(listIANAFiles(tzdataDir), backzoneFiles.__contains__) - - # Read zone and link infos. - (zones, links) = readIANAFiles(tzdataDir, tzfiles) - (backzones, backlinks) = readIANAFiles(tzdataDir, bkfiles) - - if not ignoreBackzone: - comment = """\ -// This file was generated with historical, pre-1970 backzone information -// respected. Therefore, every zone key listed below is its own Zone, not -// a Link to a modern-day target as IANA ignoring backzones would say. - -""" - else: - comment = """\ -// This file was generated while ignoring historical, pre-1970 backzone -// information. Therefore, every zone key listed below is part of a Link -// whose target is the corresponding value. - -""" - - generateTzDataLinkTestContent( - testDir, - version, - "timeZone_backzone.js", - comment + "// Backzone zones derived from IANA Time Zone Database.", - ( - (zone, zone if not ignoreBackzone else links[zone]) - for zone in backzones - if zone in links - ), - ) - - -def generateTzDataTestBackzoneLinks(tzdataDir, version, ignoreBackzone, testDir): - backzoneFiles = {"backzone"} - (bkfiles, tzfiles) = partition(listIANAFiles(tzdataDir), backzoneFiles.__contains__) - - # Read zone and link infos. - (zones, links) = readIANAFiles(tzdataDir, tzfiles) - (backzones, backlinks) = readIANAFiles(tzdataDir, bkfiles) - - if not ignoreBackzone: - comment = """\ -// This file was generated with historical, pre-1970 backzone information -// respected. Therefore, every zone key listed below points to a target -// in the backzone file and not to its modern-day target as IANA ignoring -// backzones would say. - -""" - else: - comment = """\ -// This file was generated while ignoring historical, pre-1970 backzone -// information. Therefore, every zone key listed below is part of a Link -// whose target is the corresponding value ignoring any backzone entries. - -""" - - generateTzDataLinkTestContent( - testDir, - version, - "timeZone_backzone_links.js", - comment + "// Backzone links derived from IANA Time Zone Database.", - ( - (zone, target if not ignoreBackzone else links[zone]) - for (zone, target) in backlinks.items() - ), - ) - - def generateTzDataTestVersion(tzdataDir, version, testDir): fileName = "timeZone_version.js" @@ -2956,32 +2949,11 @@ def generateTzDataTestVersion(tzdataDir, version, testDir): ) -def generateTzDataTestCanonicalZones( - tzdataDir, version, ignoreBackzone, ignoreFactory, testDir -): +def generateTzDataTestCanonicalZones(tzdataDir, version, ignoreFactory, testDir): fileName = "supportedValuesOf-timeZones-canonical.js" # Read zone and link infos. - (ianaZones, _) = readIANATimeZones(tzdataDir, ignoreBackzone, ignoreFactory) - - # Replace Etc/GMT and Etc/UTC with UTC. - ianaZones.remove(Zone("Etc/GMT")) - ianaZones.remove(Zone("Etc/UTC")) - ianaZones.add(Zone("UTC")) - - # See findIncorrectICUZones() for why Asia/Hanoi has to be special-cased. - ianaZones.remove(Zone("Asia/Hanoi")) - - if not ignoreBackzone: - comment = """\ -// This file was generated with historical, pre-1970 backzone information -// respected. -""" - else: - comment = """\ -// This file was generated while ignoring historical, pre-1970 backzone -// information. -""" + (zones, _) = availableNamedTimeZoneIdentifiers(tzdataDir, ignoreFactory) with io.open( os.path.join(testDir, fileName), mode="w", encoding="utf-8", newline="" @@ -2992,11 +2964,9 @@ def generateTzDataTestCanonicalZones( println("") println(generatedFileWarning) println(tzdataVersionComment.format(version)) - println("") - println(comment) println("const zones = [") - for zone in sorted(ianaZones): + for zone in sorted(zones): println(f' "{zone}",') println("];") @@ -3012,19 +2982,14 @@ def generateTzDataTestCanonicalZones( ) -def generateTzDataTests(tzdataDir, version, ignoreBackzone, ignoreFactory, testDir): +def generateTzDataTests(tzdataDir, version, ignoreFactory, testDir): dtfTestDir = os.path.join(testDir, "DateTimeFormat") if not os.path.isdir(dtfTestDir): raise RuntimeError("not a directory: %s" % dtfTestDir) - generateTzDataTestBackwardLinks(tzdataDir, version, ignoreBackzone, dtfTestDir) - generateTzDataTestNotBackwardLinks(tzdataDir, version, ignoreBackzone, dtfTestDir) - generateTzDataTestBackzone(tzdataDir, version, ignoreBackzone, dtfTestDir) - generateTzDataTestBackzoneLinks(tzdataDir, version, ignoreBackzone, dtfTestDir) + generateTzDataTestLinks(tzdataDir, version, ignoreFactory, dtfTestDir) generateTzDataTestVersion(tzdataDir, version, dtfTestDir) - generateTzDataTestCanonicalZones( - tzdataDir, version, ignoreBackzone, ignoreFactory, testDir - ) + generateTzDataTestCanonicalZones(tzdataDir, version, ignoreFactory, testDir) def updateTzdata(topsrcdir, args): @@ -3045,11 +3010,11 @@ def updateTzdata(topsrcdir, args): tzDir = args.tz if tzDir is not None and not (os.path.isdir(tzDir) or os.path.isfile(tzDir)): raise RuntimeError("not a directory or file: %s" % tzDir) - ignoreBackzone = args.ignore_backzone - # TODO: Accept or ignore the placeholder time zone "Factory"? - ignoreFactory = False out = args.out + # Ignore the placeholder time zone "Factory". + ignoreFactory = True + version = icuTzDataVersion(icuTzDir) url = ( "https://www.iana.org/time-zones/repository/releases/tzdata%s.tar.gz" % version @@ -3061,7 +3026,6 @@ def updateTzdata(topsrcdir, args): print("\ttzdata directory|file: %s" % tzDir) print("\tICU directory: %s" % icuDir) print("\tICU timezone directory: %s" % icuTzDir) - print("\tIgnore backzone file: %s" % ignoreBackzone) print("\tOutput file: %s" % out) print("") @@ -3073,12 +3037,11 @@ def updateFrom(f): icuDir, icuTzDir, version, - ignoreBackzone, ignoreFactory, out, ) generateTzDataTests( - TzDataFile(tar), version, ignoreBackzone, ignoreFactory, intlTestDir + TzDataFile(tar), version, ignoreFactory, intlTestDir ) elif os.path.isdir(f): processTimeZones( @@ -3086,13 +3049,10 @@ def updateFrom(f): icuDir, icuTzDir, version, - ignoreBackzone, ignoreFactory, out, ) - generateTzDataTests( - TzDataDir(f), version, ignoreBackzone, ignoreFactory, intlTestDir - ) + generateTzDataTests(TzDataDir(f), version, ignoreFactory, intlTestDir) else: raise RuntimeError("unknown format") @@ -4084,17 +4044,6 @@ def EnsureHttps(v): help="Local tzdata directory or file, if omitted downloads tzdata " "distribution from https://www.iana.org/time-zones/", ) - # ICU doesn't include the backzone file by default, but we still like to - # use the backzone time zone names to avoid user confusion. This does lead - # to formatting "historic" dates (pre-1970 era) with the wrong time zone, - # but that's probably acceptable for now. - parser_tz.add_argument( - "--ignore-backzone", - action="store_true", - help="Ignore tzdata's 'backzone' file. Can be enabled to generate more " - "accurate time zone canonicalization reflecting the actual time " - "zones as used by ICU.", - ) parser_tz.add_argument( "--out", default=os.path.join(thisDir, "TimeZoneDataGenerated.h"), diff --git a/js/src/jit-test/tests/resist-fingerprinting/timezone.js b/js/src/jit-test/tests/resist-fingerprinting/timezone.js index f85e8ff1a5e11..bc202412fa0ce 100644 --- a/js/src/jit-test/tests/resist-fingerprinting/timezone.js +++ b/js/src/jit-test/tests/resist-fingerprinting/timezone.js @@ -14,7 +14,7 @@ let originalDT = Intl.DateTimeFormat("en-US", { timeStyle: "full", }); assertEq(originalDT.format(original).endsWith("Pacific Standard Time"), true); -assertEq(originalDT.resolvedOptions().timeZone, "PST8PDT"); +assertEq(originalDT.resolvedOptions().timeZone, "America/Los_Angeles"); let global = newGlobal({forceUTC: true}); diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js deleted file mode 100644 index b9869f309fc19..0000000000000 --- a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone.js +++ /dev/null @@ -1,163 +0,0 @@ -// |reftest| skip-if(!this.hasOwnProperty("Intl")) - -// Generated by make_intl_data.py. DO NOT EDIT. -// tzdata version = 2024b - -const tzMapper = [ - x => x, - x => x.toUpperCase(), - x => x.toLowerCase(), -]; - -// This file was generated with historical, pre-1970 backzone information -// respected. Therefore, every zone key listed below is its own Zone, not -// a Link to a modern-day target as IANA ignoring backzones would say. - -// Backzone zones derived from IANA Time Zone Database. -const links = { - "Africa/Accra": "Africa/Accra", - "Africa/Addis_Ababa": "Africa/Addis_Ababa", - "Africa/Asmara": "Africa/Asmara", - "Africa/Bamako": "Africa/Bamako", - "Africa/Bangui": "Africa/Bangui", - "Africa/Banjul": "Africa/Banjul", - "Africa/Blantyre": "Africa/Blantyre", - "Africa/Brazzaville": "Africa/Brazzaville", - "Africa/Bujumbura": "Africa/Bujumbura", - "Africa/Conakry": "Africa/Conakry", - "Africa/Dakar": "Africa/Dakar", - "Africa/Dar_es_Salaam": "Africa/Dar_es_Salaam", - "Africa/Djibouti": "Africa/Djibouti", - "Africa/Douala": "Africa/Douala", - "Africa/Freetown": "Africa/Freetown", - "Africa/Gaborone": "Africa/Gaborone", - "Africa/Harare": "Africa/Harare", - "Africa/Kampala": "Africa/Kampala", - "Africa/Kigali": "Africa/Kigali", - "Africa/Kinshasa": "Africa/Kinshasa", - "Africa/Libreville": "Africa/Libreville", - "Africa/Lome": "Africa/Lome", - "Africa/Luanda": "Africa/Luanda", - "Africa/Lubumbashi": "Africa/Lubumbashi", - "Africa/Lusaka": "Africa/Lusaka", - "Africa/Malabo": "Africa/Malabo", - "Africa/Maseru": "Africa/Maseru", - "Africa/Mbabane": "Africa/Mbabane", - "Africa/Mogadishu": "Africa/Mogadishu", - "Africa/Niamey": "Africa/Niamey", - "Africa/Nouakchott": "Africa/Nouakchott", - "Africa/Ouagadougou": "Africa/Ouagadougou", - "Africa/Porto-Novo": "Africa/Porto-Novo", - "Africa/Timbuktu": "Africa/Timbuktu", - "America/Anguilla": "America/Anguilla", - "America/Antigua": "America/Antigua", - "America/Argentina/ComodRivadavia": "America/Argentina/ComodRivadavia", - "America/Aruba": "America/Aruba", - "America/Atikokan": "America/Atikokan", - "America/Blanc-Sablon": "America/Blanc-Sablon", - "America/Cayman": "America/Cayman", - "America/Coral_Harbour": "America/Coral_Harbour", - "America/Creston": "America/Creston", - "America/Curacao": "America/Curacao", - "America/Dominica": "America/Dominica", - "America/Ensenada": "America/Ensenada", - "America/Grenada": "America/Grenada", - "America/Guadeloupe": "America/Guadeloupe", - "America/Montreal": "America/Montreal", - "America/Montserrat": "America/Montserrat", - "America/Nassau": "America/Nassau", - "America/Nipigon": "America/Nipigon", - "America/Pangnirtung": "America/Pangnirtung", - "America/Port_of_Spain": "America/Port_of_Spain", - "America/Rainy_River": "America/Rainy_River", - "America/Rosario": "America/Rosario", - "America/St_Kitts": "America/St_Kitts", - "America/St_Lucia": "America/St_Lucia", - "America/St_Thomas": "America/St_Thomas", - "America/St_Vincent": "America/St_Vincent", - "America/Thunder_Bay": "America/Thunder_Bay", - "America/Tortola": "America/Tortola", - "America/Yellowknife": "America/Yellowknife", - "Antarctica/DumontDUrville": "Antarctica/DumontDUrville", - "Antarctica/McMurdo": "Antarctica/McMurdo", - "Antarctica/Syowa": "Antarctica/Syowa", - "Asia/Aden": "Asia/Aden", - "Asia/Bahrain": "Asia/Bahrain", - "Asia/Brunei": "Asia/Brunei", - "Asia/Chongqing": "Asia/Chongqing", - "Asia/Harbin": "Asia/Harbin", - "Asia/Kashgar": "Asia/Kashgar", - "Asia/Kuala_Lumpur": "Asia/Kuala_Lumpur", - "Asia/Kuwait": "Asia/Kuwait", - "Asia/Muscat": "Asia/Muscat", - "Asia/Phnom_Penh": "Asia/Phnom_Penh", - "Asia/Tel_Aviv": "Asia/Tel_Aviv", - "Asia/Vientiane": "Asia/Vientiane", - "Atlantic/Jan_Mayen": "Atlantic/Jan_Mayen", - "Atlantic/Reykjavik": "Atlantic/Reykjavik", - "Atlantic/St_Helena": "Atlantic/St_Helena", - "Australia/Currie": "Australia/Currie", - "CET": "CET", - "CST6CDT": "CST6CDT", - "EET": "EET", - "EST": "EST", - "EST5EDT": "EST5EDT", - "Europe/Amsterdam": "Europe/Amsterdam", - "Europe/Belfast": "Europe/Belfast", - "Europe/Copenhagen": "Europe/Copenhagen", - "Europe/Guernsey": "Europe/Guernsey", - "Europe/Isle_of_Man": "Europe/Isle_of_Man", - "Europe/Jersey": "Europe/Jersey", - "Europe/Ljubljana": "Europe/Ljubljana", - "Europe/Luxembourg": "Europe/Luxembourg", - "Europe/Monaco": "Europe/Monaco", - "Europe/Oslo": "Europe/Oslo", - "Europe/Sarajevo": "Europe/Sarajevo", - "Europe/Skopje": "Europe/Skopje", - "Europe/Stockholm": "Europe/Stockholm", - "Europe/Tiraspol": "Europe/Tiraspol", - "Europe/Uzhgorod": "Europe/Uzhgorod", - "Europe/Vaduz": "Europe/Vaduz", - "Europe/Zagreb": "Europe/Zagreb", - "Europe/Zaporozhye": "Europe/Zaporozhye", - "HST": "HST", - "Indian/Antananarivo": "Indian/Antananarivo", - "Indian/Christmas": "Indian/Christmas", - "Indian/Cocos": "Indian/Cocos", - "Indian/Comoro": "Indian/Comoro", - "Indian/Kerguelen": "Indian/Kerguelen", - "Indian/Mahe": "Indian/Mahe", - "Indian/Mayotte": "Indian/Mayotte", - "Indian/Reunion": "Indian/Reunion", - "MET": "MET", - "MST": "MST", - "MST7MDT": "MST7MDT", - "PST8PDT": "PST8PDT", - "Pacific/Chuuk": "Pacific/Chuuk", - "Pacific/Enderbury": "Pacific/Enderbury", - "Pacific/Funafuti": "Pacific/Funafuti", - "Pacific/Johnston": "Pacific/Johnston", - "Pacific/Majuro": "Pacific/Majuro", - "Pacific/Midway": "Pacific/Midway", - "Pacific/Pohnpei": "Pacific/Pohnpei", - "Pacific/Saipan": "Pacific/Saipan", - "Pacific/Wake": "Pacific/Wake", - "Pacific/Wallis": "Pacific/Wallis", - "WET": "WET", -}; - -for (let [linkName, target] of Object.entries(links)) { - if (target === "Etc/UTC" || target === "Etc/GMT") - target = "UTC"; - - for (let map of tzMapper) { - let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)}); - let resolvedTimeZone = dtf.resolvedOptions().timeZone; - assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`); - } -} - - -if (typeof reportCompare === "function") - reportCompare(0, 0, "ok"); - diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js deleted file mode 100644 index bae11d0417ce8..0000000000000 --- a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backzone_links.js +++ /dev/null @@ -1,48 +0,0 @@ -// |reftest| skip-if(!this.hasOwnProperty("Intl")) - -// Generated by make_intl_data.py. DO NOT EDIT. -// tzdata version = 2024b - -const tzMapper = [ - x => x, - x => x.toUpperCase(), - x => x.toLowerCase(), -]; - -// This file was generated with historical, pre-1970 backzone information -// respected. Therefore, every zone key listed below points to a target -// in the backzone file and not to its modern-day target as IANA ignoring -// backzones would say. - -// Backzone links derived from IANA Time Zone Database. -const links = { - "Africa/Asmera": "Africa/Asmara", - "America/Kralendijk": "America/Curacao", - "America/Lower_Princes": "America/Curacao", - "America/Marigot": "America/Port_of_Spain", - "America/St_Barthelemy": "America/Port_of_Spain", - "America/Virgin": "America/St_Thomas", - "Antarctica/South_Pole": "Antarctica/McMurdo", - "Arctic/Longyearbyen": "Europe/Oslo", - "Asia/Chungking": "Asia/Chongqing", - "Iceland": "Atlantic/Reykjavik", - "Pacific/Ponape": "Pacific/Pohnpei", - "Pacific/Truk": "Pacific/Chuuk", - "Pacific/Yap": "Pacific/Chuuk", -}; - -for (let [linkName, target] of Object.entries(links)) { - if (target === "Etc/UTC" || target === "Etc/GMT") - target = "UTC"; - - for (let map of tzMapper) { - let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)}); - let resolvedTimeZone = dtf.resolvedOptions().timeZone; - assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`); - } -} - - -if (typeof reportCompare === "function") - reportCompare(0, 0, "ok"); - diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backward_links.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_links.js similarity index 72% rename from js/src/tests/non262/Intl/DateTimeFormat/timeZone_backward_links.js rename to js/src/tests/non262/Intl/DateTimeFormat/timeZone_links.js index c95c42888897b..38b0b5c36f894 100644 --- a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_backward_links.js +++ b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_links.js @@ -9,46 +9,58 @@ const tzMapper = [ x => x.toLowerCase(), ]; -// Link names derived from IANA Time Zone Database, backward file. +// Link names derived from IANA Time Zone Database. const links = { "Africa/Asmera": "Africa/Asmara", + "Africa/Timbuktu": "Africa/Bamako", + "America/Argentina/ComodRivadavia": "America/Argentina/Catamarca", "America/Atka": "America/Adak", "America/Buenos_Aires": "America/Argentina/Buenos_Aires", "America/Catamarca": "America/Argentina/Catamarca", + "America/Coral_Harbour": "America/Atikokan", "America/Cordoba": "America/Argentina/Cordoba", + "America/Ensenada": "America/Tijuana", "America/Fort_Wayne": "America/Indiana/Indianapolis", "America/Godthab": "America/Nuuk", "America/Indianapolis": "America/Indiana/Indianapolis", "America/Jujuy": "America/Argentina/Jujuy", "America/Knox_IN": "America/Indiana/Knox", - "America/Kralendijk": "America/Curacao", "America/Louisville": "America/Kentucky/Louisville", - "America/Lower_Princes": "America/Curacao", - "America/Marigot": "America/Port_of_Spain", "America/Mendoza": "America/Argentina/Mendoza", + "America/Montreal": "America/Toronto", + "America/Nipigon": "America/Toronto", + "America/Pangnirtung": "America/Iqaluit", "America/Porto_Acre": "America/Rio_Branco", + "America/Rainy_River": "America/Winnipeg", + "America/Rosario": "America/Argentina/Cordoba", "America/Santa_Isabel": "America/Tijuana", "America/Shiprock": "America/Denver", - "America/St_Barthelemy": "America/Port_of_Spain", + "America/Thunder_Bay": "America/Toronto", "America/Virgin": "America/St_Thomas", + "America/Yellowknife": "America/Edmonton", "Antarctica/South_Pole": "Antarctica/McMurdo", - "Arctic/Longyearbyen": "Europe/Oslo", "Asia/Ashkhabad": "Asia/Ashgabat", "Asia/Calcutta": "Asia/Kolkata", "Asia/Choibalsan": "Asia/Ulaanbaatar", - "Asia/Chungking": "Asia/Chongqing", + "Asia/Chongqing": "Asia/Shanghai", + "Asia/Chungking": "Asia/Shanghai", "Asia/Dacca": "Asia/Dhaka", + "Asia/Harbin": "Asia/Shanghai", "Asia/Istanbul": "Europe/Istanbul", + "Asia/Kashgar": "Asia/Urumqi", "Asia/Katmandu": "Asia/Kathmandu", "Asia/Macao": "Asia/Macau", "Asia/Rangoon": "Asia/Yangon", "Asia/Saigon": "Asia/Ho_Chi_Minh", + "Asia/Tel_Aviv": "Asia/Jerusalem", "Asia/Thimbu": "Asia/Thimphu", "Asia/Ujung_Pandang": "Asia/Makassar", "Asia/Ulan_Bator": "Asia/Ulaanbaatar", "Atlantic/Faeroe": "Atlantic/Faroe", + "Atlantic/Jan_Mayen": "Arctic/Longyearbyen", "Australia/ACT": "Australia/Sydney", "Australia/Canberra": "Australia/Sydney", + "Australia/Currie": "Australia/Hobart", "Australia/LHI": "Australia/Lord_Howe", "Australia/NSW": "Australia/Sydney", "Australia/North": "Australia/Darwin", @@ -62,6 +74,8 @@ const links = { "Brazil/DeNoronha": "America/Noronha", "Brazil/East": "America/Sao_Paulo", "Brazil/West": "America/Manaus", + "CET": "Europe/Brussels", + "CST6CDT": "America/Chicago", "Canada/Atlantic": "America/Halifax", "Canada/Central": "America/Winnipeg", "Canada/Eastern": "America/Toronto", @@ -73,29 +87,34 @@ const links = { "Chile/Continental": "America/Santiago", "Chile/EasterIsland": "Pacific/Easter", "Cuba": "America/Havana", + "EET": "Europe/Athens", + "EST": "America/Panama", + "EST5EDT": "America/New_York", "Egypt": "Africa/Cairo", "Eire": "Europe/Dublin", - "Etc/GMT+0": "Etc/GMT", - "Etc/GMT-0": "Etc/GMT", - "Etc/GMT0": "Etc/GMT", - "Etc/Greenwich": "Etc/GMT", - "Etc/UCT": "Etc/UTC", - "Etc/Universal": "Etc/UTC", - "Etc/Zulu": "Etc/UTC", - "Europe/Bratislava": "Europe/Prague", - "Europe/Busingen": "Europe/Zurich", + "Etc/GMT": "UTC", + "Etc/GMT+0": "UTC", + "Etc/GMT-0": "UTC", + "Etc/GMT0": "UTC", + "Etc/Greenwich": "UTC", + "Etc/UCT": "UTC", + "Etc/UTC": "UTC", + "Etc/Universal": "UTC", + "Etc/Zulu": "UTC", + "Europe/Belfast": "Europe/London", "Europe/Kiev": "Europe/Kyiv", - "Europe/Mariehamn": "Europe/Helsinki", "Europe/Nicosia": "Asia/Nicosia", - "Europe/Podgorica": "Europe/Belgrade", - "Europe/San_Marino": "Europe/Rome", - "Europe/Vatican": "Europe/Rome", + "Europe/Tiraspol": "Europe/Chisinau", + "Europe/Uzhgorod": "Europe/Kyiv", + "Europe/Zaporozhye": "Europe/Kyiv", "GB": "Europe/London", "GB-Eire": "Europe/London", - "GMT+0": "Etc/GMT", - "GMT-0": "Etc/GMT", - "GMT0": "Etc/GMT", - "Greenwich": "Etc/GMT", + "GMT": "UTC", + "GMT+0": "UTC", + "GMT-0": "UTC", + "GMT0": "UTC", + "Greenwich": "UTC", + "HST": "Pacific/Honolulu", "Hongkong": "Asia/Hong_Kong", "Iceland": "Atlantic/Reykjavik", "Iran": "Asia/Tehran", @@ -104,6 +123,9 @@ const links = { "Japan": "Asia/Tokyo", "Kwajalein": "Pacific/Kwajalein", "Libya": "Africa/Tripoli", + "MET": "Europe/Brussels", + "MST": "America/Phoenix", + "MST7MDT": "America/Denver", "Mexico/BajaNorte": "America/Tijuana", "Mexico/BajaSur": "America/Mazatlan", "Mexico/General": "America/Mexico_City", @@ -111,6 +133,9 @@ const links = { "NZ-CHAT": "Pacific/Chatham", "Navajo": "America/Denver", "PRC": "Asia/Shanghai", + "PST8PDT": "America/Los_Angeles", + "Pacific/Enderbury": "Pacific/Kanton", + "Pacific/Johnston": "Pacific/Honolulu", "Pacific/Ponape": "Pacific/Pohnpei", "Pacific/Samoa": "Pacific/Pago_Pago", "Pacific/Truk": "Pacific/Chuuk", @@ -121,7 +146,7 @@ const links = { "ROK": "Asia/Seoul", "Singapore": "Asia/Singapore", "Turkey": "Europe/Istanbul", - "UCT": "Etc/UTC", + "UCT": "UTC", "US/Alaska": "America/Anchorage", "US/Aleutian": "America/Adak", "US/Arizona": "America/Phoenix", @@ -134,10 +159,10 @@ const links = { "US/Mountain": "America/Denver", "US/Pacific": "America/Los_Angeles", "US/Samoa": "Pacific/Pago_Pago", - "UTC": "Etc/UTC", - "Universal": "Etc/UTC", + "Universal": "UTC", "W-SU": "Europe/Moscow", - "Zulu": "Etc/UTC", + "WET": "Europe/Lisbon", + "Zulu": "UTC", }; for (let [linkName, target] of Object.entries(links)) { diff --git a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js b/js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js deleted file mode 100644 index 904a8bad829ec..0000000000000 --- a/js/src/tests/non262/Intl/DateTimeFormat/timeZone_notbackward_links.js +++ /dev/null @@ -1,31 +0,0 @@ -// |reftest| skip-if(!this.hasOwnProperty("Intl")) - -// Generated by make_intl_data.py. DO NOT EDIT. -// tzdata version = 2024b - -const tzMapper = [ - x => x, - x => x.toUpperCase(), - x => x.toLowerCase(), -]; - -// Link names derived from IANA Time Zone Database, excluding backward file. -const links = { - "GMT": "Etc/GMT", -}; - -for (let [linkName, target] of Object.entries(links)) { - if (target === "Etc/UTC" || target === "Etc/GMT") - target = "UTC"; - - for (let map of tzMapper) { - let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(linkName)}); - let resolvedTimeZone = dtf.resolvedOptions().timeZone; - assertEq(resolvedTimeZone, target, `${linkName} -> ${target}`); - } -} - - -if (typeof reportCompare === "function") - reportCompare(0, 0, "ok"); - diff --git a/js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js b/js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js index 9b184fd2b25a2..39b1ab7b2bf47 100644 --- a/js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js +++ b/js/src/tests/non262/Intl/DateTimeFormat/tz-environment-variable.js @@ -40,10 +40,10 @@ function inTimeZone(tzname, fn) { } const timeZones = [ - { id: "EST5EDT" }, - { id: "CST6CDT" }, - { id: "MST7MDT" }, - { id: "PST8PDT" }, + { id: "EST5EDT", normalized: "America/New_York" }, + { id: "CST6CDT", normalized: "America/Chicago" }, + { id: "MST7MDT", normalized: "America/Denver" }, + { id: "PST8PDT", normalized: "America/Los_Angeles" }, // ICU on non-Windows platforms doesn't accept these three time zone // identifiers, cf. isValidOlsonID in $ICU/source/common/putil.cpp. We // could add support for them, but it seems unlikely they're used in diff --git a/js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js b/js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js index 5b399c8930a39..77fc910ddb589 100644 --- a/js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js +++ b/js/src/tests/non262/Intl/supportedValuesOf-timeZones-canonical.js @@ -2,10 +2,6 @@ // Generated by make_intl_data.py. DO NOT EDIT. // tzdata version = 2024b - -// This file was generated with historical, pre-1970 backzone information -// respected. - const zones = [ "Africa/Abidjan", "Africa/Accra", @@ -56,7 +52,6 @@ const zones = [ "Africa/Ouagadougou", "Africa/Porto-Novo", "Africa/Sao_Tome", - "Africa/Timbuktu", "Africa/Tripoli", "Africa/Tunis", "Africa/Windhoek", @@ -67,7 +62,6 @@ const zones = [ "America/Araguaina", "America/Argentina/Buenos_Aires", "America/Argentina/Catamarca", - "America/Argentina/ComodRivadavia", "America/Argentina/Cordoba", "America/Argentina/Jujuy", "America/Argentina/La_Rioja", @@ -99,7 +93,6 @@ const zones = [ "America/Chicago", "America/Chihuahua", "America/Ciudad_Juarez", - "America/Coral_Harbour", "America/Costa_Rica", "America/Creston", "America/Cuiaba", @@ -113,7 +106,6 @@ const zones = [ "America/Edmonton", "America/Eirunepe", "America/El_Salvador", - "America/Ensenada", "America/Fort_Nelson", "America/Fortaleza", "America/Glace_Bay", @@ -141,12 +133,15 @@ const zones = [ "America/Juneau", "America/Kentucky/Louisville", "America/Kentucky/Monticello", + "America/Kralendijk", "America/La_Paz", "America/Lima", "America/Los_Angeles", + "America/Lower_Princes", "America/Maceio", "America/Managua", "America/Manaus", + "America/Marigot", "America/Martinique", "America/Matamoros", "America/Mazatlan", @@ -158,11 +153,9 @@ const zones = [ "America/Moncton", "America/Monterrey", "America/Montevideo", - "America/Montreal", "America/Montserrat", "America/Nassau", "America/New_York", - "America/Nipigon", "America/Nome", "America/Noronha", "America/North_Dakota/Beulah", @@ -171,7 +164,6 @@ const zones = [ "America/Nuuk", "America/Ojinaga", "America/Panama", - "America/Pangnirtung", "America/Paramaribo", "America/Phoenix", "America/Port-au-Prince", @@ -179,19 +171,18 @@ const zones = [ "America/Porto_Velho", "America/Puerto_Rico", "America/Punta_Arenas", - "America/Rainy_River", "America/Rankin_Inlet", "America/Recife", "America/Regina", "America/Resolute", "America/Rio_Branco", - "America/Rosario", "America/Santarem", "America/Santiago", "America/Santo_Domingo", "America/Sao_Paulo", "America/Scoresbysund", "America/Sitka", + "America/St_Barthelemy", "America/St_Johns", "America/St_Kitts", "America/St_Lucia", @@ -200,7 +191,6 @@ const zones = [ "America/Swift_Current", "America/Tegucigalpa", "America/Thule", - "America/Thunder_Bay", "America/Tijuana", "America/Toronto", "America/Tortola", @@ -208,7 +198,6 @@ const zones = [ "America/Whitehorse", "America/Winnipeg", "America/Yakutat", - "America/Yellowknife", "Antarctica/Casey", "Antarctica/Davis", "Antarctica/DumontDUrville", @@ -220,6 +209,7 @@ const zones = [ "Antarctica/Syowa", "Antarctica/Troll", "Antarctica/Vostok", + "Arctic/Longyearbyen", "Asia/Aden", "Asia/Almaty", "Asia/Amman", @@ -237,7 +227,6 @@ const zones = [ "Asia/Bishkek", "Asia/Brunei", "Asia/Chita", - "Asia/Chongqing", "Asia/Colombo", "Asia/Damascus", "Asia/Dhaka", @@ -246,7 +235,6 @@ const zones = [ "Asia/Dushanbe", "Asia/Famagusta", "Asia/Gaza", - "Asia/Harbin", "Asia/Hebron", "Asia/Ho_Chi_Minh", "Asia/Hong_Kong", @@ -258,7 +246,6 @@ const zones = [ "Asia/Kabul", "Asia/Kamchatka", "Asia/Karachi", - "Asia/Kashgar", "Asia/Kathmandu", "Asia/Khandyga", "Asia/Kolkata", @@ -293,7 +280,6 @@ const zones = [ "Asia/Tashkent", "Asia/Tbilisi", "Asia/Tehran", - "Asia/Tel_Aviv", "Asia/Thimphu", "Asia/Tokyo", "Asia/Tomsk", @@ -311,7 +297,6 @@ const zones = [ "Atlantic/Canary", "Atlantic/Cape_Verde", "Atlantic/Faroe", - "Atlantic/Jan_Mayen", "Atlantic/Madeira", "Atlantic/Reykjavik", "Atlantic/South_Georgia", @@ -320,7 +305,6 @@ const zones = [ "Australia/Adelaide", "Australia/Brisbane", "Australia/Broken_Hill", - "Australia/Currie", "Australia/Darwin", "Australia/Eucla", "Australia/Hobart", @@ -329,11 +313,6 @@ const zones = [ "Australia/Melbourne", "Australia/Perth", "Australia/Sydney", - "CET", - "CST6CDT", - "EET", - "EST", - "EST5EDT", "Etc/GMT+1", "Etc/GMT+10", "Etc/GMT+11", @@ -364,12 +343,13 @@ const zones = [ "Europe/Andorra", "Europe/Astrakhan", "Europe/Athens", - "Europe/Belfast", "Europe/Belgrade", "Europe/Berlin", + "Europe/Bratislava", "Europe/Brussels", "Europe/Bucharest", "Europe/Budapest", + "Europe/Busingen", "Europe/Chisinau", "Europe/Copenhagen", "Europe/Dublin", @@ -388,15 +368,18 @@ const zones = [ "Europe/Luxembourg", "Europe/Madrid", "Europe/Malta", + "Europe/Mariehamn", "Europe/Minsk", "Europe/Monaco", "Europe/Moscow", "Europe/Oslo", "Europe/Paris", + "Europe/Podgorica", "Europe/Prague", "Europe/Riga", "Europe/Rome", "Europe/Samara", + "Europe/San_Marino", "Europe/Sarajevo", "Europe/Saratov", "Europe/Simferopol", @@ -405,19 +388,15 @@ const zones = [ "Europe/Stockholm", "Europe/Tallinn", "Europe/Tirane", - "Europe/Tiraspol", "Europe/Ulyanovsk", - "Europe/Uzhgorod", "Europe/Vaduz", + "Europe/Vatican", "Europe/Vienna", "Europe/Vilnius", "Europe/Volgograd", "Europe/Warsaw", "Europe/Zagreb", - "Europe/Zaporozhye", "Europe/Zurich", - "Factory", - "HST", "Indian/Antananarivo", "Indian/Chagos", "Indian/Christmas", @@ -429,10 +408,6 @@ const zones = [ "Indian/Mauritius", "Indian/Mayotte", "Indian/Reunion", - "MET", - "MST", - "MST7MDT", - "PST8PDT", "Pacific/Apia", "Pacific/Auckland", "Pacific/Bougainville", @@ -440,7 +415,6 @@ const zones = [ "Pacific/Chuuk", "Pacific/Easter", "Pacific/Efate", - "Pacific/Enderbury", "Pacific/Fakaofo", "Pacific/Fiji", "Pacific/Funafuti", @@ -449,7 +423,6 @@ const zones = [ "Pacific/Guadalcanal", "Pacific/Guam", "Pacific/Honolulu", - "Pacific/Johnston", "Pacific/Kanton", "Pacific/Kiritimati", "Pacific/Kosrae", @@ -474,7 +447,6 @@ const zones = [ "Pacific/Wake", "Pacific/Wallis", "UTC", - "WET", ]; let supported = Intl.supportedValuesOf("timeZone");