tor-browser

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

timeZone.js (4094B)


      1 // |reftest| skip-if(!this.hasOwnProperty("Intl"))
      2 
      3 const tzMapper = [
      4    x => x,
      5    x => x.toUpperCase(),
      6    x => x.toLowerCase(),
      7 ];
      8 
      9 
     10 const utcTimeZones = [
     11    // Etc/UTC and Etc/GMT are normalized to UTC.
     12    "Etc/UTC", "Etc/GMT",
     13 
     14    // Links to Etc/GMT. (tzdata/etcetera)
     15    "GMT", "Etc/Greenwich", "Etc/GMT-0", "Etc/GMT+0", "Etc/GMT0",
     16 
     17    // Links to Etc/UTC. (tzdata/etcetera)
     18    "Etc/Universal", "Etc/Zulu",
     19 
     20    // Links to Etc/GMT. (tzdata/backward)
     21    "GMT+0", "GMT-0", "GMT0", "Greenwich",
     22 
     23    // Links to Etc/UTC. (tzdata/backward)
     24    "UTC", "Universal", "Zulu", "Etc/UCT", "UCT",
     25 ];
     26 
     27 for (let timeZone of utcTimeZones) {
     28    for (let map of tzMapper) {
     29        let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
     30        assertEq(dtf.resolvedOptions().timeZone, "UTC");
     31    }
     32 }
     33 
     34 
     35 const invalidTimeZones = [
     36    "", "null", "undefined", "UTC\0",
     37 
     38    // ICU time zone name for invalid time zones.
     39    "Etc/Unknown",
     40 
     41    // ICU custom time zones.
     42    "GMT-1", "GMT+1", "GMT-10", "GMT+10",
     43    "GMT-10:00", "GMT+10:00",
     44    "GMT-1000", "GMT+1000",
     45 
     46    // Legacy ICU time zones.
     47    "ACT", "AET", "AGT", "ART", "AST", "BET", "BST", "CAT", "CNT", "CST",
     48    "CTT", "EAT", "ECT", "IET", "IST", "JST", "MIT", "NET", "NST", "PLT",
     49    "PNT", "PRT", "PST", "SST", "VST",
     50 
     51    // Deprecated IANA time zones.
     52    "SystemV/AST4ADT", "SystemV/EST5EDT", "SystemV/CST6CDT", "SystemV/MST7MDT",
     53    "SystemV/PST8PDT", "SystemV/YST9YDT", "SystemV/AST4", "SystemV/EST5",
     54    "SystemV/CST6", "SystemV/MST7", "SystemV/PST8", "SystemV/YST9", "SystemV/HST10",
     55 ];
     56 
     57 for (let timeZone of invalidTimeZones) {
     58    for (let map of tzMapper) {
     59        assertThrowsInstanceOf(() => {
     60            new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
     61        }, RangeError);
     62    }
     63 }
     64 
     65 
     66 // GMT[+-]hh is invalid, but Etc/GMT[+-]hh is a valid IANA time zone.
     67 for (let gmtOffset = -14; gmtOffset <= 12; ++gmtOffset) {
     68    // Skip Etc/GMT0.
     69    if (gmtOffset === 0)
     70        continue;
     71 
     72    let timeZone = `Etc/GMT${gmtOffset > 0 ? "+" : ""}${gmtOffset}`;
     73    for (let map of tzMapper) {
     74        let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
     75        assertEq(dtf.resolvedOptions().timeZone, timeZone);
     76    }
     77 }
     78 
     79 
     80 const invalidEtcGMTNames = [
     81  // Out of bounds GMT offset.
     82  "Etc/GMT-15", "Etc/GMT+13",
     83 
     84  // Etc/GMT[+-]hh:mm isn't a IANA time zone name.
     85  "Etc/GMT-10:00", "Etc/GMT+10:00",
     86  "Etc/GMT-1000", "Etc/GMT+1000",
     87 ];
     88 
     89 for (let timeZone of invalidEtcGMTNames) {
     90    for (let map of tzMapper) {
     91        assertThrowsInstanceOf(() => {
     92            new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
     93        }, RangeError);
     94    }
     95 }
     96 
     97 
     98 // RangeError is thrown for primitive values, because ToString(<primitive>)
     99 // isn't a valid time zone name.
    100 for (let nonStrings of [null, 0, 0.5, true, false]) {
    101    assertThrowsInstanceOf(() => {
    102        new Intl.DateTimeFormat(undefined, {timeZone: nonStrings});
    103    }, RangeError);
    104 }
    105 
    106 // ToString(<symbol>) throws TypeError.
    107 assertThrowsInstanceOf(() => {
    108    new Intl.DateTimeFormat(undefined, {timeZone: Symbol()});
    109 }, TypeError);
    110 
    111 // |undefined| or absent "timeZone" option selects the default time zone.
    112 {
    113    let {timeZone: tzAbsent} = new Intl.DateTimeFormat(undefined, {}).resolvedOptions();
    114    let {timeZone: tzUndefined} = new Intl.DateTimeFormat(undefined, {timeZone: undefined}).resolvedOptions();
    115 
    116    assertEq(typeof tzAbsent, "string");
    117    assertEq(typeof tzUndefined, "string");
    118    assertEq(tzUndefined, tzAbsent);
    119 
    120    // The default time zone isn't a link name.
    121    let {timeZone: tzDefault} = new Intl.DateTimeFormat(undefined, {timeZone: tzAbsent}).resolvedOptions();
    122    assertEq(tzDefault, tzAbsent);
    123 }
    124 
    125 // Objects are converted through ToString().
    126 {
    127    let timeZone = "Europe/Warsaw";
    128    let obj = {
    129        toString() {
    130            return timeZone;
    131        }
    132    };
    133    let dtf = new Intl.DateTimeFormat(undefined, {timeZone: obj});
    134    assertEq(dtf.resolvedOptions().timeZone, timeZone);
    135 }
    136 
    137 
    138 if (typeof reportCompare === "function")
    139    reportCompare(0, 0, "ok");