diff --git a/polyfill/test/validStrings.mjs b/polyfill/test/validStrings.mjs
index f494499023..7c5f1f6d9e 100644
--- a/polyfill/test/validStrings.mjs
+++ b/polyfill/test/validStrings.mjs
@@ -245,23 +245,28 @@ const timeFraction = withCode(temporalDecimalFraction, (data, result) => {
data.microsecond = +fraction.slice(3, 6);
data.nanosecond = +fraction.slice(6, 9);
});
+
function saveOffset(data, result) {
data.offset = ES.ParseDateTimeUTCOffset(result);
}
-
-const utcOffsetWithSubMinuteComponents = (extended) =>
- seq(temporalSign, hour, timeSeparator(extended), minuteSecond, timeSeparator(extended), minuteSecond, [
- temporalDecimalFraction
+const utcOffset = (subMinutePrecision) =>
+ seq(temporalSign, hour, [
+ choice(
+ seq(
+ timeSeparator(true),
+ minuteSecond,
+ subMinutePrecision ? [timeSeparator(true), minuteSecond, [temporalDecimalFraction]] : empty
+ ),
+ seq(
+ timeSeparator(false),
+ minuteSecond,
+ subMinutePrecision ? [timeSeparator(false), minuteSecond, [temporalDecimalFraction]] : empty
+ )
+ )
]);
-const utcOffsetMinutePrecision = seq(temporalSign, hour, [
- choice(seq(timeSeparator(true), minuteSecond), seq(timeSeparator(false), minuteSecond))
-]);
-const utcOffsetSubMinutePrecision = withCode(
- choice(utcOffsetMinutePrecision, utcOffsetWithSubMinuteComponents(true), utcOffsetWithSubMinuteComponents(false)),
- saveOffset
-);
-const dateTimeUTCOffset = (z) => (z ? choice(utcDesignator, utcOffsetSubMinutePrecision) : utcOffsetSubMinutePrecision);
-const timeZoneUTCOffsetName = utcOffsetMinutePrecision;
+const dateTimeUTCOffset = (z) =>
+ z ? choice(utcDesignator, withCode(utcOffset(true), saveOffset)) : withCode(utcOffset(true), saveOffset);
+const timeZoneUTCOffsetName = utcOffset(false);
const timeZoneIANAName = choice(...timezoneNames);
const timeZoneIdentifier = withCode(
choice(timeZoneUTCOffsetName, timeZoneIANAName),
diff --git a/spec/abstractops.html b/spec/abstractops.html
index 984476bf32..5ade797e0f 100644
--- a/spec/abstractops.html
+++ b/spec/abstractops.html
@@ -1278,28 +1278,22 @@
ISO 8601 grammar
TimeFraction :::
TemporalDecimalFraction
- UTCOffsetWithSubMinuteComponents[Extended] :::
- TemporalSign Hour TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TemporalDecimalFraction?
-
NormalizedUTCOffset :::
ASCIISign Hour TimeSeparator[+Extended] MinuteSecond
- UTCOffsetMinutePrecision :::
+ UTCOffset[SubMinutePrecision] :::
TemporalSign Hour
TemporalSign Hour TimeSeparator[+Extended] MinuteSecond
TemporalSign Hour TimeSeparator[~Extended] MinuteSecond
-
- UTCOffsetSubMinutePrecision :::
- UTCOffsetMinutePrecision
- UTCOffsetWithSubMinuteComponents[+Extended]
- UTCOffsetWithSubMinuteComponents[~Extended]
+ [+SubMinutePrecision] TemporalSign Hour TimeSeparator[+Extended] MinuteSecond TimeSeparator[+Extended] MinuteSecond TemporalDecimalFraction?
+ [+SubMinutePrecision] TemporalSign Hour TimeSeparator[~Extended] MinuteSecond TimeSeparator[~Extended] MinuteSecond TemporalDecimalFraction?
DateTimeUTCOffset[Z] :::
[+Z] UTCDesignator
- UTCOffsetSubMinutePrecision
+ UTCOffset[+SubMinutePrecision]
TimeZoneUTCOffsetName :::
- UTCOffsetMinutePrecision
+ UTCOffset[~SubMinutePrecision]
TZLeadingChar :::
Alpha
@@ -1631,8 +1625,8 @@
1. Set _timeZoneResult_.[[TimeZoneAnnotation]] to CodePointsToString(_identifier_).
1. If _parseResult_ contains a |UTCDesignator| Parse Node, then
1. Set _timeZoneResult_.[[Z]] to *true*.
- 1. Else if _parseResult_ contains a |UTCOffsetSubMinutePrecision| Parse Node, then
- 1. Let _offset_ be the source text matched by the |UTCOffsetSubMinutePrecision| Parse Node contained within _parseResult_.
+ 1. Else if _parseResult_ contains a |UTCOffset[+SubMinutePrecision]| Parse Node, then
+ 1. Let _offset_ be the source text matched by the |UTCOffset[+SubMinutePrecision]| Parse Node contained within _parseResult_.
1. Set _timeZoneResult_.[[OffsetString]] to CodePointsToString(_offset_).
1. Return the Record {
[[Year]]: _yearMV_,
diff --git a/spec/intl.html b/spec/intl.html
index ba25a18dda..1650b79e0a 100644
--- a/spec/intl.html
+++ b/spec/intl.html
@@ -650,7 +650,7 @@
1. If _toLocaleStringTimeZone_ is present, throw a *TypeError* exception.
1. Set _timeZone_ to ? ToString(_timeZone_).
1. If IsTimeZoneOffsetString(_timeZone_) is *true*, then
- 1. Let _parseResult_ be ParseText(StringToCodePoints(_timeZone_), |UTCOffset||UTCOffsetMinutePrecision|).
+ 1. Let _parseResult_ be ParseText(StringToCodePoints(_timeZone_), |UTCOffset||UTCOffset[~SubMinutePrecision]|).
1. Assert: _parseResult_ is a Parse Node.
1. If _parseResult_ contains more than one |MinuteSecond| Parse Node, throw a *RangeError* exception.
1. Let _offsetNanoseconds_ be ParseTimeZoneOffsetString? ParseDateTimeUTCOffset(_timeZone_).
diff --git a/spec/mainadditions.html b/spec/mainadditions.html
index 977ce9b0aa..5f9f1d28d9 100644
--- a/spec/mainadditions.html
+++ b/spec/mainadditions.html
@@ -252,8 +252,8 @@ Time Zone Offset String FormatFormats
ECMAScript defines string interchange formats for UTC offsets, derived from ISO 8601.
- UTC offsets that represent offset time zone identifiers, or that are intended for interoperability with ISO 8601, use only hours and minutes and are specified by |UTCOffsetMinutePrecision|.
- UTC offsets that represent the offset of a named or custom time zone can be more precise, and are specified by |UTCOffsetSubMinutePrecision|.
+ UTC offsets that represent offset time zone identifiers, or that are intended for interoperability with ISO 8601, use only hours and minutes and are specified by |UTCOffset[~SubMinutePrecision]|.
+ UTC offsets that represent the offset of a named or custom time zone can be more precise, and are specified by |UTCOffset[+SubMinutePrecision]|.
These formats are described by the ISO String grammar in .
@@ -461,7 +461,7 @@
- 1. Let _parseResult_ be ParseText(StringToCodePoints(_offsetString_), |UTCOffset||UTCOffsetSubMinutePrecision|).
+ 1. Let _parseResult_ be ParseText(StringToCodePoints(_offsetString_), |UTCOffset||UTCOffset[+SubMinutePrecision]|).
1. Assert: _parseResult_ is not a List of errors.
1. If _parseResult_ is a List of errors, throw a *RangeError* exception.
1. Assert: _parseResult_ contains a |TemporalSign| Parse Node.