Skip to content

Commit 1f65a30

Browse files
committed
Polyfill: Cap day span at <100% of day length in ZonedDateTime.round()
The assertion in the previous code was a problem in cases where a backwards UTC shift spanned across midnight (i.e. from a time after midnight to a time before midnight, not starting or ending at midnight.) It would produce a span of startNs...thisNs that was longer than 100% of the day length, which failed the assertion, but would also mess up rounding modes (would expand to 200% of the day length, for example.) See: #3312
1 parent 3b8337a commit 1f65a30

1 file changed

Lines changed: 8 additions & 2 deletions

File tree

polyfill/lib/zoneddatetime.mjs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ export class ZonedDateTime {
287287

288288
// first, round the underlying DateTime fields
289289
const timeZone = GetSlot(this, TIME_ZONE);
290-
const thisNs = GetSlot(this, EPOCHNANOSECONDS);
290+
let thisNs = GetSlot(this, EPOCHNANOSECONDS);
291291
const iso = dateTime(this);
292292
let epochNanoseconds;
293293

@@ -301,7 +301,13 @@ export class ZonedDateTime {
301301
assert(thisNs.geq(startNs), 'cannot produce an instant during a day that occurs before start-of-day instant');
302302

303303
const endNs = ES.GetStartOfDay(timeZone, dateEnd);
304-
assert(thisNs.lt(endNs), 'cannot produce an instant during a day that occurs on or after end-of-day instant');
304+
// Handle the case where a transition starts after midnight and falls back
305+
// to before midnight, and pieces of two calendar days are interleaved.
306+
// endNs is the start of the first piece of the second calendar day, so if
307+
// thisNs is inside the second piece of the first calendar day, it can be
308+
// outside of the box defined by start-of-day and end-of-day.
309+
// https://github.com/tc39/proposal-temporal/issues/3312
310+
if (thisNs.geq(endNs)) thisNs = endNs.minus(bigInt.one);
305311

306312
const dayLengthNs = endNs.subtract(startNs);
307313
const dayProgressNs = TimeDuration.fromEpochNsDiff(thisNs, startNs);

0 commit comments

Comments
 (0)