-
Notifications
You must be signed in to change notification settings - Fork 173
Description
While reviewing #2003 and looking at implementation concerns raised in #1863, I looked more closely at the PlainYearMonth add/subtract algorithm in the spec and noticed interesting behavior: when adding (or subtracting a negative duration), we treat the receiver as if it were the first nanosecond of the month, but when subtracting we treat it as the last nanosecond of the month. The same behavior seems to be present in PlainDate add/subtract, where subtracting one hour from a PlainDate yields the same value because we treat the receiver as if was the last nanosecond of the day.
Is this behavior what callers will expect? Specifically:
- AFAICT, in all other Temporal contexts we treat a PlainDate as if it were the first nanosecond of the day, and treat a PlainYearMonth as the first nanosecond of the month. Why is this case different? For example, in Calendar-ignoring
comparebehaves unexpectedly for non-ISO calendar PlainYearMonth comparisons #1846 we decided that when comparing PlainYearMonth instances across calendars, we'd treat a PlainYearMonth as the first day of the calendar month. - When combining addition with converting PlainDate to PlainDateTime (or PlainYearMonth to PlainDate or PlainDateTime), will it be expected that order-of-operations should cause different results? EDIT: I updated this example to be clearer
/** add a duration to a date, and then return a PlainDateTime for noon on the resulting day */
function noonOnAddedDate1(plainDate, duration) {
const pdt = plainDate.toPlainDateTime();
const added = pdt.add(duration);
const result = added.withPlainTime('12:00');
return result;
}
/** same as above, but will return different result for negative durations with nonzero time units */
function noonOnAddedDate2(plainDate, duration) {
const added = plainDate.add(duration);
const result = added.toPlainDateTime('12:00');
return result;
}
date = Temporal.PlainDate.from('2020-01-01');
duration = Temporal.Duration.from('-PT12H');
noonOnAddedDate1(date, duration);
// => 2019-12-31T12:00:00
noonOnAddedDate2(date, duration);
// => 2020-01-01T12:00:00Anyway, seems like we have three options:
- Leave current behavior as-is, and document it
- Change add/subtract to be consistent with other part of temporal by treating PlainDate as the first nanosecond of the day and PlainYearMonth as the first nanosecond of the month.
- Throw if the user calls PlainDate add/subtract with non-zero hours (or smaller units) or calls PlainYearMonth with non-zero days (or smaller units).
My opinion is that (2) or (3) will be easier for callers to predict and understand. I'm not sure any developer will expect (1) unless they read the spec or (when we update them) the docs.