diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index 8619a96b9..d0b7f3cb3 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -2098,13 +2098,38 @@ export function GetPossibleEpochNanoseconds(timeZone, isoDateTime) {
const { year, month, day, hour, minute, second, millisecond, microsecond, nanosecond } = isoDateTime;
const offsetMinutes = ParseTimeZoneIdentifier(timeZone).offsetMinutes;
if (offsetMinutes !== undefined) {
- return [
- GetUTCEpochNanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond).subtract(
- offsetMinutes * 60e9
- )
- ];
+ const balanced = BalanceISODateTime(
+ year,
+ month,
+ day,
+ hour,
+ minute - offsetMinutes,
+ second,
+ millisecond,
+ microsecond,
+ nanosecond
+ );
+ if (MathAbs(ISODateToEpochDays(balanced.year, balanced.month - 1, balanced.day)) > 1e8) {
+ throw new RangeErrorCtor('date/time value is outside the supported range');
+ }
+ const epochNs = GetUTCEpochNanoseconds(
+ balanced.year,
+ balanced.month,
+ balanced.day,
+ balanced.hour,
+ balanced.minute,
+ balanced.second,
+ balanced.millisecond,
+ balanced.microsecond,
+ balanced.nanosecond
+ );
+ ValidateEpochNanoseconds(epochNs);
+ return [epochNs];
}
+ if (MathAbs(ISODateToEpochDays(year, month - 1, day)) > 1e8) {
+ throw new RangeErrorCtor('date/time value is outside the supported range');
+ }
return GetNamedTimeZoneEpochNanoseconds(
timeZone,
year,
@@ -2693,6 +2718,7 @@ export function GetNamedTimeZoneEpochNanoseconds(
) {
return undefined;
}
+ ValidateEpochNanoseconds(epochNanoseconds);
return epochNanoseconds;
}
]);
diff --git a/spec/timezone.html b/spec/timezone.html
index 07dbb5f9f..c22315fd9 100644
--- a/spec/timezone.html
+++ b/spec/timezone.html
@@ -357,10 +357,12 @@
1. Let _parseResult_ be ! ParseTimeZoneIdentifier(_timeZone_).
1. If _parseResult_.[[OffsetMinutes]] is not ~empty~, then
- 1. Let _offsetNanoseconds_ be _parseResult_.[[OffsetMinutes]] × (60 × 109).
- 1. Let _epochNanoseconds_ be GetUTCEpochNanoseconds(_isoDateTime_.[[Year]], _isoDateTime_.[[Month]], _isoDateTime_.[[Day]], _isoDateTime_.[[Hour]], _isoDateTime_.[[Minute]], _isoDateTime_.[[Second]], _isoDateTime_.[[Millisecond]], _isoDateTime_.[[Microsecond]], _isoDateTime_.[[Nanosecond]]) - ℤ(_offsetNanoseconds_).
+ 1. Let _balanced_ be BalanceISODateTime(_isoDateTime_.[[Year]], _isoDateTime_.[[Month]], _isoDateTime_.[[Day]], _isoDateTime_.[[Hour]], _isoDateTime_.[[Minute]] - _parseResult_.[[OffsetMinutes]], _isoDateTime_.[[Second]], _isoDateTime_.[[Millisecond]], _isoDateTime_.[[Microsecond]], _isoDateTime_.[[Nanosecond]]).
+ 1. If abs(ISODateToEpochDays(_balanced_.[[Year]], _balanced_.[[Month]] - 1, _balanced_.[[Day]])) > 108, throw a *RangeError* exception.
+ 1. Let _epochNanoseconds_ be GetUTCEpochNanoseconds(_balanced_.[[Year]], _balanced_.[[Month]], _balanced_.[[Day]], _balanced_.[[Hour]], _balanced_.[[Minute]], _balanced_.[[Second]], _balanced_.[[Millisecond]], _balanced_.[[Microsecond]], _balanced_.[[Nanosecond]]).
1. Let _possibleEpochNanoseconds_ be « _epochNanoseconds_ ».
1. Else,
+ 1. If abs(ISODateToEpochDays(_isoDateTime_.[[Year]], _isoDateTime_.[[Month]] - 1, _isoDateTime_.[[Day]])) > 108, throw a *RangeError* exception.
1. Let _possibleEpochNanoseconds_ be GetNamedTimeZoneEpochNanoseconds(_parseResult_.[[Name]], _isoDateTime_.[[Year]], _isoDateTime_.[[Month]], _isoDateTime_.[[Day]], _isoDateTime_.[[Hour]], _isoDateTime_.[[Minute]], _isoDateTime_.[[Second]], _isoDateTime_.[[Millisecond]], _isoDateTime_.[[Microsecond]], _isoDateTime_.[[Nanosecond]]).
1. For each value _epochNanoseconds_ in _possibleEpochNanoseconds_, do
1. If IsValidEpochNanoseconds(_epochNanoseconds_) is *false*, throw a *RangeError* exception.