tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

canonicalize-timezone.js (5382B)


      1 // Copyright 2025 Igalia, S.L. All rights reserved.
      2 // This code is governed by the BSD license found in the LICENSE file.
      3 /*---
      4 esid: sec-use-of-iana-time-zone-database
      5 description: >
      6  Primary and non-primary time zone identifiers must correspond with IANA Time
      7  Zone Database Zones and Link names, subject to explicit exceptions, and must
      8  direct time zone name canonicalization.
      9 info: |
     10    AvailableNamedTimeZoneIdentifiers ( )
     11 
     12    1. Let _identifiers_ be a List containing the String value of each Zone or Link name in the IANA Time Zone Database.
     13    2. ...
     14    3. ...
     15    4. Let _result_ be a new empty List.
     16    5. For each element _identifier_ of _identifiers_, do
     17      a. Let _primary_ be _identifier_.
     18      b. If _identifier_ is a Link name in the IANA Time Zone Database and _identifier_ is not present in the “TZ” column of <code>zone.tab</code> of the IANA Time Zone Database, then
     19        i. Let _zone_ be the Zone name that _identifier_ resolves to, according to the rules for resolving Link names in the IANA Time Zone Database.
     20        ii. If _zone_ starts with *"Etc/"*, then
     21          1. Set _primary_ to _zone_.
     22        iii. Else,
     23          1. Let _identifierCountryCode_ be the <a href="https://www.iso.org/glossary-for-iso-3166.html">ISO 3166-1 Alpha-2</a> country code whose territory contains the geographical area corresponding to _identifier_.
     24          2. Let _zoneCountryCode_ be the ISO 3166-1 Alpha-2 country code whose territory contains the geographical area corresponding to _zone_.
     25          3. If _identifierCountryCode_ is _zoneCountryCode_, then
     26            a. Set _primary_ to _zone_.
     27          4. Else,
     28            a. Let _countryCodeLineCount_ be the number of lines in file <code>zone.tab</code> of the IANA Time Zone Database where the “country-code” column is _identifierCountryCode_.
     29            b. If _countryCodeLineCount_ is 1, then
     30              i. Let _countryCodeLine_ be the line in file <code>zone.tab</code> of the IANA Time Zone Database where the “country-code” column is _identifierCountryCode_.
     31              ii. Set _primary_ to the contents of the “TZ” column of _countryCodeLine_.
     32            c. Else,
     33              i. Let _backzone_ be *undefined*.
     34              ii. Let _backzoneLinkLines_ be the List of lines in the file <code>backzone</code> of the IANA Time Zone Database that start with either *"Link "* or *"#PACKRATLIST zone.tab Link "*.
     35              iii. ...
     36              iv. Assert: _backzone_ is not *undefined*.
     37              v. Set _primary_ to _backzone_.
     38      c. If _primary_ is one of *"Etc/UTC"*, *"Etc/GMT"*, or *"GMT"*, set _primary_ to *"UTC"*.
     39      d. ...
     40      e. Let _record_ be the Time Zone Identifier Record { [[Identifier]]: _identifier_, [[PrimaryIdentifier]]: _primary_ }.
     41      f. Append _record_ to _result_.
     42    6. ...
     43    7. Return _result_.
     44 
     45    GetAvailableNamedTimeZoneIdentifier ( _timeZoneIdentifier_ )
     46 
     47    1. For each element _record_ of AvailableNamedTimeZoneIdentifiers(), do
     48      a. If _record_.[[Identifier]] is an ASCII-case-insensitive match for _timeZoneIdentifier_, return record.
     49    2. Return ~empty~.
     50 
     51    CreateDateTimeFormat ( _newTarget_, _locales_, _options_, _required_, _defaults_ )
     52 
     53    29. If IsTimeZoneOffsetString(_timeZone_) is *true*, then
     54      ...
     55    30. Else,
     56      a. Let _timeZoneIdentifierRecord_ be GetAvailableNamedTimeZoneIdentifier(_timeZone_).
     57      b. If _timeZoneIdentifierRecord_ is ~empty~, throw a RangeError exception.
     58      c. Set _timeZone_ to _timeZoneIdentifierRecord_.[[PrimaryIdentifier]].
     59 features: [canonical-tz]
     60 ---*/
     61 
     62 const timeZones = [
     63  // Europe/Prague is not a Link name.
     64  ["Europe/Prague", "Europe/Prague"],
     65 
     66  // `backward` identifies "Europe/Bratislava" as a Link name targeting "Europe/Prague":
     67  //   Link	Europe/Prague		Europe/Bratislava
     68  // Europe/Bratislava's country code "SK" has only one time zone in `zone.tab`.
     69  ["Europe/Bratislava", "Europe/Bratislava"],
     70 
     71  // `backward` identifies "Australia/Canberra" as a Link targeting "Australia/Sydney":
     72  //   Link	Australia/Sydney	Australia/Canberra
     73  // Both share the country code "AU".
     74  ["Australia/Canberra", "Australia/Sydney"],
     75 
     76  // `backward` identifies "Atlantic/Jan_Mayen" as a Link name targeting "Europe/Berlin":
     77  //   Link	Europe/Berlin		Atlantic/Jan_Mayen
     78  // Atlantic/Jan_Mayen's country code "SJ" has only one time zone in `zone.tab`.
     79  ["Atlantic/Jan_Mayen", "Arctic/Longyearbyen"],
     80 
     81  // `backward` identifies "Pacific/Truk" as a Link name targeting "Pacific/Port_Moresby":
     82  //   Link	Pacific/Port_Moresby	Pacific/Truk	#= Pacific/Chuuk
     83  // Pacific/Chuuk's country code "FM" has multiple time zones in `zone.tab`.
     84  // `backzone` identifies "Pacific/Truk" as a Link name targeting "Pacific/Chuuk":
     85  //   Link Pacific/Chuuk Pacific/Truk
     86  ["Pacific/Truk", "Pacific/Chuuk"],
     87 
     88  // `backward` identifies "Etc/UCT" as a Link name targeting "Etc/UTC":
     89  //   Link	Etc/UTC			Etc/UCT
     90  ["Etc/UCT", "UTC"],
     91 
     92  // `backward` identifies "Etc/GMT0" as a Link name targeting "Etc/GMT":
     93  //   Link	Etc/GMT			Etc/GMT0
     94  ["Etc/GMT0", "UTC"]
     95 ];
     96 
     97 for (const [timeZone, linkTarget] of timeZones) {
     98  assert.sameValue(
     99    new Intl.DateTimeFormat([], { timeZone }).resolvedOptions().timeZone,
    100    timeZone,
    101    "Time zone name " + timeZone + " should be preserved and not canonicalized to " + linkTarget
    102  );
    103 }
    104 
    105 reportCompare(0, 0);