Skip to content

Commit 1117eaf

Browse files
gibson042ptomato
authored andcommitted
Normative: Require strict matching with a precise ZonedDateTime offset
Fixes #3099
1 parent 5fa1c59 commit 1117eaf

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

polyfill/lib/ecmascript.mjs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,14 @@ export function GetTemporalRelativeToOption(options) {
993993
} else if (!offset) {
994994
offsetBehaviour = 'wall';
995995
}
996+
// Allow imprecise offset matching unless the provided offset is precise
996997
matchMinutes = true;
998+
if (offset) {
999+
const offsetParseResult = Call(RegExpPrototypeExec, OFFSET_WITH_PARTS, [offset]);
1000+
assert(offsetParseResult, 'offset string must re-parse');
1001+
const offsetSecondsPart = offsetParseResult[4];
1002+
if (offsetSecondsPart) matchMinutes = false;
1003+
}
9971004
} else if (z) {
9981005
throw new RangeErrorCtor(
9991006
'Z designator not supported for PlainDate relativeTo; either remove the Z or add a bracketed time zone'
@@ -1521,7 +1528,14 @@ export function ToTemporalZonedDateTime(item, options = undefined) {
15211528
}
15221529
if (!calendar) calendar = 'iso8601';
15231530
calendar = CanonicalizeCalendar(calendar);
1524-
matchMinute = true; // ISO strings may specify offset with less precision
1531+
// Allow imprecise offset matching unless the provided offset is precise
1532+
matchMinute = true;
1533+
if (offset) {
1534+
const offsetParseResult = Call(RegExpPrototypeExec, OFFSET_WITH_PARTS, [offset]);
1535+
assert(offsetParseResult, 'offset string must re-parse');
1536+
const offsetSecondsPart = offsetParseResult[4];
1537+
if (offsetSecondsPart) matchMinute = false;
1538+
}
15251539
const resolvedOptions = GetOptionsObject(options);
15261540
disambiguation = GetTemporalDisambiguationOption(resolvedOptions);
15271541
offsetOpt = GetTemporalOffsetOption(resolvedOptions, 'reject');

spec/abstractops.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,10 @@ <h1>
645645
1. Else if _offsetString_ is ~empty~, then
646646
1. Set _offsetBehaviour_ to ~wall~.
647647
1. Set _matchBehaviour_ to ~match-minutes~.
648+
1. If _offsetString_ is not ~empty~, then
649+
1. Let _offsetParseResult_ be ParseText(StringToCodePoints(_offsetString_), |UTCOffset[+SubMinutePrecision]|).
650+
1. Assert: _offsetParseResult_ is a Parse Node.
651+
1. If _offsetParseResult_ contains more than one |MinuteSecond| Parse Node, set _matchBehaviour_ to ~match-exactly~.
648652
1. Let _calendar_ be _result_.[[Calendar]].
649653
1. If _calendar_ is ~empty~, set _calendar_ to *"iso8601"*.
650654
1. Set _calendar_ to ? CanonicalizeCalendar(_calendar_).

spec/zoneddatetime.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,10 @@ <h1>
991991
1. If _calendar_ is ~empty~, set _calendar_ to *"iso8601"*.
992992
1. Set _calendar_ to ? CanonicalizeCalendar(_calendar_).
993993
1. Set _matchBehaviour_ to ~match-minutes~.
994+
1. If _offsetString_ is not ~empty~, then
995+
1. Let _offsetParseResult_ be ParseText(StringToCodePoints(_offsetString_), |UTCOffset[+SubMinutePrecision]|).
996+
1. Assert: _offsetParseResult_ is a Parse Node.
997+
1. If _offsetParseResult_ contains more than one |MinuteSecond| Parse Node, set _matchBehaviour_ to ~match-exactly~.
994998
1. Let _resolvedOptions_ be ? GetOptionsObject(_options_).
995999
1. Let _disambiguation_ be ? GetTemporalDisambiguationOption(_resolvedOptions_).
9961000
1. Let _offsetOption_ be ? GetTemporalOffsetOption(_resolvedOptions_, ~reject~).

0 commit comments

Comments
 (0)