round() with smallestUnit: 'month' and smallestUnit: 'year' should be allowed on PlainDate, PlainDateTime, ZonedDateTime, and (year only) PlainYearMonth.
In V1, PlainDate lacks a round method, and PlainDateTime and ZonedDateTime are both limited to smallestUnit: 'day' or smaller.
Rounding up would advance to the first day of the next month or year, respectively. (Not the last day of the month or year.)
roundingIncrement would be limited to 1 or undefined, because the number of months in a year can vary in lunisolar calendars like Hebrew or Chinese that have 12 months in non-leap years but 13 months in leap years.
Advantages:
Better consistency across Temporal types
Easier support for use cases like 'closest start of year'
/** Are we halfway done with the year yet? */
function isHalfwayDoneWithYear(date) {
return date.round({ smallestUnit: 'year' }).year === date.year;
}
// current workaround
function isHalfwayDoneWithYear(date) {
const daysSoFar = date.since(date.with({month: 1, day: 1}));
return daysSoFar >= date.daysInYear / 2;
}
Avoids bugs in non-ISO calendars, e.g.
// proposed
date = date.round({smallestUnit: 'month', roundingMode: 'ceil'});
// current, which breaks in the chinese or hebrew calendar where years can have 12 or 13 months
if (date.day > 1) {
date = date.month === 12 ? date.with({ year: date.year + 1, month: 1 }) : date.with({ month: date.month + 1 });
}
// BTW, here's a less obvious alternative to buggy code above
if (date.day > 1) date = date.add({month: 1}).with({day: 1})
Concerns:
Workaround is pretty easy today, so not sure this change is necessarily needed. Workaround is:
Year and month rounding already exists on until and since and Duration.prototype.round, just not on the round methods of PlainDate, PlainDateTime, ZonedDateTime.
round()
withsmallestUnit: 'month'
andsmallestUnit: 'year'
should be allowed on PlainDate, PlainDateTime, ZonedDateTime, and (year
only) PlainYearMonth.In V1, PlainDate lacks a
round
method, and PlainDateTime and ZonedDateTime are both limited tosmallestUnit: 'day'
or smaller.Rounding up would advance to the first day of the next month or year, respectively. (Not the last day of the month or year.)
roundingIncrement
would be limited to1
orundefined
, because the number of months in a year can vary in lunisolar calendars like Hebrew or Chinese that have 12 months in non-leap years but 13 months in leap years.Advantages:
Concerns:
Prior art:
Year and month rounding already exists on
until
andsince
andDuration.prototype.round
, just not on theround
methods ofPlainDate
,PlainDateTime
,ZonedDateTime
.See https://github.com/tc39/proposal-temporal/issues/1785 for previous discussion.
Constraints / corner cases:
None that I know of, but I can add if they're raised in comments.