Skip to content

Commit d938843

Browse files
cjtennyjustingrant
authored andcommitted
Normative: Treat daysInMonth as count of all days rather than number of the last day
Updates PlainYearMonth arithmetic accordingly and clarifies language around non-ISO calendar operations. Fixes #1315 Co-authored-by: Guillaume Emont <[email protected]> UPSTREAM_COMMIT=3aa97fa6fec9bb83272e7f62c497d163f83255ae
1 parent 85a6e94 commit d938843

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

lib/ecmascript.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5664,16 +5664,27 @@ export function AddDurationToOrSubtractDurationFromPlainYearMonth(
56645664
const calendar = GetSlot(yearMonth, CALENDAR);
56655665
const fieldNames = CalendarFields(calendar, ['monthCode', 'year'] as const);
56665666
const fields = PrepareTemporalFields(yearMonth, fieldNames, []);
5667-
const sign = DurationSign(years, months, weeks, days, 0, 0, 0, 0, 0, 0);
5668-
fields.day = sign < 0 ? CalendarDaysInMonth(calendar, yearMonth) : 1;
5667+
const fieldsCopy = ObjectCreate(null);
5668+
CopyDataProperties(fieldsCopy, fields, []);
5669+
fields.day = 1;
56695670
// PrepareTemporalFields returns a type where 'day' is potentially undefined,
5670-
// and TS doesn't narrow the type as a result of the assignment above, so we
5671-
// cast the fields input to the new type.
5672-
const startDate = CalendarDateFromFields(calendar, fields as typeof fields & { day: number });
5671+
// but TS doesn't narrow the type as a result of the assignment above.
5672+
uncheckedAssertNarrowedType<typeof fields & { day: number }>(fields, '`day` is guaranteed to be non-undefined');
5673+
let startDate = CalendarDateFromFields(calendar, fields);
5674+
const sign = DurationSign(years, months, weeks, days, 0, 0, 0, 0, 0, 0);
5675+
const dateAdd = GetMethod(calendar, 'dateAdd');
56735676
const Duration = GetIntrinsic('%Temporal.Duration%');
5677+
if (sign < 0) {
5678+
const oneMonthDuration = new Duration(0, 1, 0, 0, 0, 0, 0, 0, 0, 0);
5679+
const nextMonth = CalendarDateAdd(calendar, startDate, oneMonthDuration, undefined, dateAdd);
5680+
const minusDayDuration = new Duration(0, 0, 0, -1, 0, 0, 0, 0, 0, 0);
5681+
const endOfMonth = CalendarDateAdd(calendar, nextMonth, minusDayDuration, undefined, dateAdd);
5682+
fieldsCopy.day = CalendarDay(calendar, endOfMonth);
5683+
startDate = CalendarDateFromFields(calendar, fieldsCopy);
5684+
}
56745685
const durationToAdd = new Duration(years, months, weeks, days, 0, 0, 0, 0, 0, 0);
56755686
const optionsCopy = CopyOptions(options);
5676-
const addedDate = CalendarDateAdd(calendar, startDate, durationToAdd, options);
5687+
const addedDate = CalendarDateAdd(calendar, startDate, durationToAdd, options, dateAdd);
56775688
const addedDateFields = PrepareTemporalFields(addedDate, fieldNames, []);
56785689

56795690
return CalendarYearMonthFromFields(calendar, addedDateFields, optionsCopy);

0 commit comments

Comments
 (0)