Discovered thanks to Firefox fuzzing: https://bugzilla.mozilla.org/show_bug.cgi?id=2029756
Reproducer:
const z = Temporal.ZonedDateTime.from("2010-03-04T23:10:00+08:00[Antarctica/Casey]");
z.round({ smallestUnit: 'day' });
What's going on here is that there was a backward UTC shift that crossed midnight. 23:10+08:00 is the repeated 23:10 wall-clock time, so it's in a piece of 2010-03-04 that occurs after a piece of 2010-03-05. In ZonedDateTime.prototype.round, we call GetStartOfDay to find the beginning and the end of the day to snap to. For the latter, GetStartOfDay disambiguates to the earlier midnight (at the end of the first piece of 2010-03-04). The assertion fails because we were not expecting the ZonedDateTime to be after the end of the day that it's supposed to round to.
Note that the relatively much more common phenomenon of a UTC shift that starts or ends at midnight, such as Brazil pre-2018, is not affected.
Also note that we use GetStartOfDay similarly to find the start of the next day in ZonedDateTime.prototype.hoursInDay. That does not fail any assertion; we already discussed it in #2938, but forgot to consider how it would affect ZonedDateTime.prototype.round. Applied to this case, z.hoursInDay could plausibly return either 24 (length of the first piece of 2010-03-04) or 27 (length from the first moment of 2010-03-04 until the last moment, including a discontiguous piece of 2010-03-05). We chose the former, and documented it as such. Whatever resolution we pick here should be consistent with hoursInDay (or else we should consider changing the hoursInDay behaviour as well.)
Discovered thanks to Firefox fuzzing: https://bugzilla.mozilla.org/show_bug.cgi?id=2029756
Reproducer:
What's going on here is that there was a backward UTC shift that crossed midnight. 23:10+08:00 is the repeated 23:10 wall-clock time, so it's in a piece of 2010-03-04 that occurs after a piece of 2010-03-05. In ZonedDateTime.prototype.round, we call GetStartOfDay to find the beginning and the end of the day to snap to. For the latter, GetStartOfDay disambiguates to the earlier midnight (at the end of the first piece of 2010-03-04). The assertion fails because we were not expecting the ZonedDateTime to be after the end of the day that it's supposed to round to.
Note that the relatively much more common phenomenon of a UTC shift that starts or ends at midnight, such as Brazil pre-2018, is not affected.
Also note that we use GetStartOfDay similarly to find the start of the next day in ZonedDateTime.prototype.hoursInDay. That does not fail any assertion; we already discussed it in #2938, but forgot to consider how it would affect ZonedDateTime.prototype.round. Applied to this case,
z.hoursInDaycould plausibly return either 24 (length of the first piece of 2010-03-04) or 27 (length from the first moment of 2010-03-04 until the last moment, including a discontiguous piece of 2010-03-05). We chose the former, and documented it as such. Whatever resolution we pick here should be consistent with hoursInDay (or else we should consider changing the hoursInDay behaviour as well.)