Skip to content

Commit 4cfea3f

Browse files
ptomatoMs2ger
authored andcommitted
Fix time zone canonicalization behaviour in DateTimeFormat test
As of the Time Zone Canonicalization proposal which is stage 3, the original time zone name should be preserved in Intl.DateTimeFormat .prototype.resolvedOptions. Add a separate test that uses Temporal.ZonedDateTime.prototype.equals to test the canonicalization behaviour.
1 parent 7cc9850 commit 4cfea3f

File tree

2 files changed

+107
-2
lines changed

2 files changed

+107
-2
lines changed

test/intl402/DateTimeFormat/canonicalize-timezone.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ info: |
5656
a. Let _timeZoneIdentifierRecord_ be GetAvailableNamedTimeZoneIdentifier(_timeZone_).
5757
b. If _timeZoneIdentifierRecord_ is ~empty~, throw a RangeError exception.
5858
c. Set _timeZone_ to _timeZoneIdentifierRecord_.[[PrimaryIdentifier]].
59+
features: [canonical-tz]
5960
---*/
6061

6162
const timeZones = [
@@ -96,7 +97,7 @@ const timeZones = [
9697
for (const [timeZone, expected] of timeZones) {
9798
assert.sameValue(
9899
new Intl.DateTimeFormat([], { timeZone }).resolvedOptions().timeZone,
99-
expected,
100-
"Time zone name " + timeZone + " should be canonicalized to " + expected
100+
timeZone,
101+
"Time zone name " + timeZone + " should be preserved and not canonicalized to " + expected
101102
);
102103
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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: [Temporal, 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, expected] of timeZones) {
98+
const z1 = new Temporal.ZonedDateTime(0n, timeZone);
99+
const z2 = new Temporal.ZonedDateTime(0n, expected);
100+
assert(
101+
z1.equals(z2),
102+
"Time zone name " + timeZone + " should be canonicalized to " + expected
103+
);
104+
}

0 commit comments

Comments
 (0)