js-temporal / proposal-temporal-v2

Future additions to Temporal
MIT License
24 stars 1 forks source link

`round` on date-having types should support month and year rounding #20

Open justingrant opened 3 years ago

justingrant commented 3 years ago

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:

Concerns:

function roundToMonthsOrYears(temporalInstance, roundOptions) { 
  const baseValues = { 
    year: temporalInstance.year, month: 1, monthCode: 'M01', day: 1,
    hour: 0, minute: 0, second: 0, millisecond: 0, microsecond: 0, nanosecond: 0
  };
  const base = temporalInstance.with(baseValues)
  const duration = base.until(temporalInstance, roundOptions);
  return base.add(duration);
}
roundToMonthsOrYears(Temporal.PlainDate.from('2021-02-15'), { smallestUnit: 'month', roundingMode: 'trunc' });
// => 2021-02-01
roundToMonthsOrYears(Temporal.PlainDate.from('2021-02-15'), { smallestUnit: 'month', roundingMode: 'ceil' });
// => 2021-03-01
roundToMonthsOrYears(Temporal.PlainDate.from('2021-02-15'), { smallestUnit: 'month', roundingMode: 'halfExpand' });
// => 2021-03-01
roundToMonthsOrYears(Temporal.PlainDate.from('2021-02-14'), { smallestUnit: 'month', roundingMode: 'halfExpand' });
// => 2021-02-01

Prior art:

Year and month rounding already exists on until and since and Duration.prototype.round, just not on the round methods of PlainDate, 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.

LinusU commented 2 years ago

I would love to have support for week as well.

e.g. I would like to do .round({ smallestUnit: 'week', roundingMode: 'trunc' }) to get the start of the week of a ZonedDateTime