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.