summaryrefslogtreecommitdiffstats
path: root/js/src/tests/Intl/DateTimeFormat/timeZone.js
blob: 94d0fdc1f14f43962ec5852774bc72de027127fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// |reftest| skip-if(!this.hasOwnProperty("Intl"))

const tzMapper = [
    x => x,
    x => x.toUpperCase(),
    x => x.toLowerCase(),
];


const utcTimeZones = [
    // Etc/UTC and Etc/GMT are normalized to UTC.
    "Etc/UTC", "Etc/GMT",

    // Links to Etc/GMT. (tzdata/etcetera)
    "GMT", "Etc/Greenwich", "Etc/GMT-0", "Etc/GMT+0", "Etc/GMT0",

    // Links to Etc/UTC. (tzdata/etcetera)
    "Etc/Universal", "Etc/Zulu",

    // Links to Etc/GMT. (tzdata/backward)
    "GMT+0", "GMT-0", "GMT0", "Greenwich",

    // Links to Etc/UTC. (tzdata/backward)
    "UTC", "Universal", "Zulu",
];

for (let timeZone of utcTimeZones) {
    for (let map of tzMapper) {
        let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
        assertEq(dtf.resolvedOptions().timeZone, "UTC");
    }
}


// ECMA-402 doesn't normalize Etc/UCT to UTC.
const uctTimeZones = [
    "Etc/UCT", "UCT",
];

for (let timeZone of uctTimeZones) {
    for (let map of tzMapper) {
        let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
        assertEq(dtf.resolvedOptions().timeZone, "Etc/UCT");
    }
}


const invalidTimeZones = [
    "", "null", "undefined", "UTC\0",

    // ICU time zone name for invalid time zones.
    "Etc/Unknown",

    // ICU custom time zones.
    "GMT-1", "GMT+1", "GMT-10", "GMT+10",
    "GMT-10:00", "GMT+10:00",
    "GMT-1000", "GMT+1000",

    // Legacy ICU time zones.
    "ACT", "AET", "AGT", "ART", "AST", "BET", "BST", "CAT", "CNT", "CST",
    "CTT", "EAT", "ECT", "IET", "IST", "JST", "MIT", "NET", "NST", "PLT",
    "PNT", "PRT", "PST", "SST", "VST",

    // Deprecated IANA time zones.
    "SystemV/AST4ADT", "SystemV/EST5EDT", "SystemV/CST6CDT", "SystemV/MST7MDT",
    "SystemV/PST8PDT", "SystemV/YST9YDT", "SystemV/AST4", "SystemV/EST5",
    "SystemV/CST6", "SystemV/MST7", "SystemV/PST8", "SystemV/YST9", "SystemV/HST10",
];

for (let timeZone of invalidTimeZones) {
    for (let map of tzMapper) {
        assertThrowsInstanceOf(() => {
            new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
        }, RangeError);
    }
}


// GMT[+-]hh is invalid, but Etc/GMT[+-]hh is a valid IANA time zone.
for (let gmtOffset = -14; gmtOffset <= 12; ++gmtOffset) {
    // Skip Etc/GMT0.
    if (gmtOffset === 0)
        continue;

    let timeZone = `Etc/GMT${gmtOffset > 0 ? "+" : ""}${gmtOffset}`;
    for (let map of tzMapper) {
        let dtf = new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
        assertEq(dtf.resolvedOptions().timeZone, timeZone);
    }
}


const invalidEtcGMTNames = [
  // Out of bounds GMT offset.
  "Etc/GMT-15", "Etc/GMT+13",

  // Etc/GMT[+-]hh:mm isn't a IANA time zone name.
  "Etc/GMT-10:00", "Etc/GMT+10:00",
  "Etc/GMT-1000", "Etc/GMT+1000",
];

for (let timeZone of invalidEtcGMTNames) {
    for (let map of tzMapper) {
        assertThrowsInstanceOf(() => {
            new Intl.DateTimeFormat(undefined, {timeZone: map(timeZone)});
        }, RangeError);
    }
}


// RangeError is thrown for primitive values, because ToString(<primitive>)
// isn't a valid time zone name.
for (let nonStrings of [null, 0, 0.5, true, false]) {
    assertThrowsInstanceOf(() => {
        new Intl.DateTimeFormat(undefined, {timeZone: nonStrings});
    }, RangeError);
}

// ToString(<symbol>) throws TypeError.
assertThrowsInstanceOf(() => {
    new Intl.DateTimeFormat(undefined, {timeZone: Symbol()});
}, TypeError);

// |undefined| or absent "timeZone" option selects the default time zone.
{
    let {timeZone: tzAbsent} = new Intl.DateTimeFormat(undefined, {}).resolvedOptions();
    let {timeZone: tzUndefined} = new Intl.DateTimeFormat(undefined, {timeZone: undefined}).resolvedOptions();

    assertEq(typeof tzAbsent, "string");
    assertEq(typeof tzUndefined, "string");
    assertEq(tzUndefined, tzAbsent);

    // The default time zone isn't a link name.
    let {timeZone: tzDefault} = new Intl.DateTimeFormat(undefined, {timeZone: tzAbsent}).resolvedOptions();
    assertEq(tzDefault, tzAbsent);
}

// Objects are converted through ToString().
{
    let timeZone = "Europe/Warsaw";
    let obj = {
        toString() {
            return timeZone;
        }
    };
    let dtf = new Intl.DateTimeFormat(undefined, {timeZone: obj});
    assertEq(dtf.resolvedOptions().timeZone, timeZone);
}


if (typeof reportCompare === "function")
    reportCompare(0, 0, "ok");