Skip to content

Commit 6c36d29

Browse files
ptomato12wrigja
authored andcommitted
Simplify ParseTemporalTimeZoneString
This was a bit of a mess. Rewrite the operation so that it tries to parse the string as a bare time zone identifier _first_, and if that fails, as an ISO string, throwing if the ISO string doesn't contain any time zone (whether Z designator, UTC offset, or IANA name). This was what the operation previously did, just much more difficult to follow. The reference polyfill mostly already worked like this, but move the IANA name canonicalization step out of ParseTemporalTimeZoneString and into its only caller, to correspond better with the spec text. This also requires bringing the time zone ID regex better in line with the grammar's |TimeZoneIdentifier| production by adding the IANA legacy names. UPSTREAM_COMMIT=eec8efab983131401c2092dd26a1f9e8d049b666
1 parent e73a8ba commit 6c36d29

File tree

3 files changed

+18
-11
lines changed

3 files changed

+18
-11
lines changed

lib/ecmascript.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,8 @@ export function RejectObjectWithCalendarOrTimeZone(item: AnyTemporalLikeType) {
343343
}
344344
}
345345
function ParseTemporalTimeZone(stringIdent: string) {
346-
let { ianaName, offset, z } = ParseTemporalTimeZoneString(stringIdent);
347-
if (ianaName) return ianaName;
346+
const { ianaName, offset, z } = ParseTemporalTimeZoneString(stringIdent);
347+
if (ianaName) return GetCanonicalTimeZoneIdentifier(ianaName);
348348
if (z) return 'UTC';
349349
return offset as string; // if !ianaName && !z then offset must be present
350350
}
@@ -533,12 +533,8 @@ export function ParseTemporalTimeZoneString(stringIdent: string): Partial<{
533533
offset: string | undefined;
534534
z: boolean | undefined;
535535
}> {
536-
try {
537-
let canonicalIdent = GetCanonicalTimeZoneIdentifier(stringIdent);
538-
if (canonicalIdent) return { ianaName: canonicalIdent.toString() };
539-
} catch {
540-
// fall through
541-
}
536+
const bareID = new RegExp(`^${PARSE.timeZoneID.source}$`, 'i');
537+
if (bareID.test(stringIdent)) return { ianaName: stringIdent };
542538
try {
543539
// Try parsing ISO string instead
544540
const result = ParseISODateTime(stringIdent);

lib/regex.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,18 @@
11
const tzComponent = /\.[-A-Za-z_]|\.\.[-A-Za-z._]{1,12}|\.[-A-Za-z_][-A-Za-z._]{0,12}|[A-Za-z_][-A-Za-z._]{0,13}/;
22
const offsetNoCapture = /(?:[+\u2212-][0-2][0-9](?::?[0-5][0-9](?::?[0-5][0-9](?:[.,]\d{1,9})?)?)?)/;
3-
const timeZoneID = new RegExp(
4-
`(?:(?:${tzComponent.source})(?:\\/(?:${tzComponent.source}))*|Etc/GMT[-+]\\d{1,2}|${offsetNoCapture.source})`
3+
export const timeZoneID = new RegExp(
4+
'(?:' +
5+
[
6+
`(?:${tzComponent.source})(?:\\/(?:${tzComponent.source}))*`,
7+
'Etc/GMT(?:0|[-+]\\d{1,2})',
8+
'GMT[-+]?0',
9+
'EST5EDT',
10+
'CST6CDT',
11+
'MST7MDT',
12+
'PST8PDT',
13+
offsetNoCapture.source
14+
].join('|') +
15+
')'
516
);
617

718
const calComponent = /[A-Za-z0-9]{3,8}/;

test/validStrings.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ const timeZoneUTCOffsetName = seq(
265265
const timeZoneIANAName = choice(...timezoneNames);
266266
const timeZoneIdentifier = withCode(
267267
choice(timeZoneUTCOffsetName, timeZoneIANAName),
268-
(data, result) => (data.ianaName = ES.GetCanonicalTimeZoneIdentifier(result).toString())
268+
(data, result) => (data.ianaName = result)
269269
);
270270
const timeZoneBracketedAnnotation = seq('[', timeZoneIdentifier, ']');
271271
const timeZoneOffsetRequired = withCode(seq(timeZoneUTCOffset, [timeZoneBracketedAnnotation]), (data) => {

0 commit comments

Comments
 (0)