Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 36 additions & 11 deletions src/builtins/core/plain_year_month.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,19 +300,25 @@ impl PlainYearMonth {
// 7. Let thisFields be ISODateToFields(calendar, yearMonth.[[ISODate]], year-month).
// 8. Set thisFields.[[Day]] to 1.
// 9. Let thisDate be ? CalendarDateFromFields(calendar, thisFields, constrain).
let mut this_iso = self.iso;
this_iso.day = 1;
this_iso.check_within_limits()?;
let this_fields = CalendarFields::from(YearMonthCalendarFields::try_from_year_month(self)?);
let this_fields = this_fields.with_day(1);
let this_date = self
.calendar()
.date_from_fields(this_fields, Overflow::Constrain)?;
// 10. Let otherFields be ISODateToFields(calendar, other.[[ISODate]], year-month).
// 11. Set otherFields.[[Day]] to 1.
// 12. Let otherDate be ? CalendarDateFromFields(calendar, otherFields, constrain).
let mut other_iso = other.iso;
other_iso.day = 1;
other_iso.check_within_limits()?;
// 13. Let dateDifference be CalendarDateUntil(calendar, thisDate, otherDate, settings.[[LargestUnit]]).
let result = self
let other_fields =
CalendarFields::from(YearMonthCalendarFields::try_from_year_month(other)?);
let other_fields = other_fields.with_day(1);
let other_date = self
.calendar()
.date_until(&this_iso, &other_iso, resolved.largest_unit)?;
.date_from_fields(other_fields, Overflow::Constrain)?;

// 13. Let dateDifference be CalendarDateUntil(calendar, thisDate, otherDate, settings.[[LargestUnit]]).
let result =
self.calendar()
.date_until(&this_date.iso, &other_date.iso, resolved.largest_unit)?;
// 14. Let yearsMonthsDifference be ! AdjustDateDurationRecord(dateDifference, 0, 0).
let result = result.date().adjust(0, Some(0), None)?;

Expand All @@ -322,9 +328,10 @@ impl PlainYearMonth {
// 16. If settings.[[SmallestUnit]] is not month or settings.[[RoundingIncrement]] ≠ 1, then
if resolved.smallest_unit != Unit::Month || resolved.increment != RoundingIncrement::ONE {
// a. Let isoDateTime be CombineISODateAndTimeRecord(thisDate, MidnightTimeRecord()).
let iso_date_time = IsoDateTime::new_unchecked(this_iso, IsoTime::default());
let iso_date_time = IsoDateTime::new_unchecked(this_date.iso, IsoTime::default());
// b. Let isoDateTimeOther be CombineISODateAndTimeRecord(otherDate, MidnightTimeRecord()).
let target_iso_date_time = IsoDateTime::new_unchecked(other_iso, IsoTime::default());
let target_iso_date_time =
IsoDateTime::new_unchecked(other_date.iso, IsoTime::default());
// c. Let destEpochNs be GetUTCEpochNanoseconds(isoDateTimeOther).
let dest_epoch_ns = target_iso_date_time.as_nanoseconds();
// d. Set duration to ? RoundRelativeDuration(duration, destEpochNs, isoDateTime, unset, calendar, resolved.[[LargestUnit]], resolved.[[RoundingIncrement]], resolved.[[SmallestUnit]], resolved.[[RoundingMode]]).
Expand Down Expand Up @@ -804,6 +811,24 @@ mod tests {
assert_eq!(until.years(), 1);
assert_eq!(since.years(), -1);
}

// Ensure that the day = 1 setting before diff works in non-ISO calendars
{
let earlier = PlainYearMonth::from_str("2000-07-02[u-ca=chinese]").unwrap();
let later = PlainYearMonth::from_str("2000-12-26[u-ca=chinese]").unwrap();
assert_eq!(earlier.month(), 6);
assert_eq!(later.month(), 12);
let settings = DifferenceSettings {
smallest_unit: Some(Unit::Month),
..Default::default()
};

let until = earlier.until(&later, settings).unwrap();
let since = earlier.since(&later, settings).unwrap();

assert_eq!(until.months(), 6);
assert_eq!(since.months(), -6);
}
}
#[test]
fn test_diff_with_different_calendars() {
Expand Down