Temporal: Wrapping at end of month, Coptic, Ethioaa, and Ethiopic calendars

Also correct some of the error message strings in the
wrapping-at-end-of-month-gregory tests
This commit is contained in:
Tim Chevalier 2025-11-19 14:29:39 -08:00 committed by Ms2ger
parent de78e27f89
commit 5ad17a2068
24 changed files with 2190 additions and 12 deletions

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindate.prototype.since
description: Tests balancing of days to months at end of month (coptic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "coptic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pi Kogi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 28, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pi Kogi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 29, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pi Kogi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 30, calendar }).since(end, { largestUnit }),
0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pi Kogi Enavot (M13)
{
const end = Temporal.PlainDate.from({ year: 1971, monthCode: "M13", day: 6, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 6, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pi Kogi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 29, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pi Kogi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 30, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 5, calendar }).since(end, { largestUnit }),
0, -3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pi Kogi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 6, calendar }).since(end, { largestUnit }),
0, -2, 0, -29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pi Kogi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDate.from({ year: 1973, monthCode: "M13", day: 5, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).since(end, { largestUnit: "months" }),
0, -40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).since(end, { largestUnit: "years" }),
-3, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 6, calendar }).since(end, { largestUnit: "months" }),
0, -39, 0, -29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pi Kogi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 7, calendar }).since(end, { largestUnit: "years" }),
-3, 0, 0, -28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 29, calendar })
.since(Temporal.PlainDate.from({ year: 1970, monthCode: "M03", day: 28, calendar }), { largestUnit: "months" }),
0, -1, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 30, calendar })
.since(Temporal.PlainDate.from({ year: 1971, monthCode: "M05", day: 29, calendar }), { largestUnit: "years" }),
-1, -3, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindate.prototype.since
description: Tests balancing of days to months at end of month (ethioaa calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethioaa";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 28, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 29, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 30, calendar }).since(end, { largestUnit }),
0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.PlainDate.from({ year: 1971, monthCode: "M13", day: 6, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 6, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 29, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 30, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 5, calendar }).since(end, { largestUnit }),
0, -3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 6, calendar }).since(end, { largestUnit }),
0, -2, 0, -29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDate.from({ year: 1973, monthCode: "M13", day: 5, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).since(end, { largestUnit: "months" }),
0, -40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).since(end, { largestUnit: "years" }),
-3, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 6, calendar }).since(end, { largestUnit: "months" }),
0, -39, 0, -29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 7, calendar }).since(end, { largestUnit: "years" }),
-3, 0, 0, -28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 29, calendar })
.since(Temporal.PlainDate.from({ year: 1970, monthCode: "M03", day: 28, calendar }), { largestUnit: "months" }),
0, -1, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 30, calendar })
.since(Temporal.PlainDate.from({ year: 1971, monthCode: "M05", day: 29, calendar }), { largestUnit: "years" }),
-1, -3, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindate.prototype.since
description: Tests balancing of days to months at end of month (ethiopic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethiopic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 28, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 29, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 30, calendar }).since(end, { largestUnit }),
0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.PlainDate.from({ year: 1971, monthCode: "M13", day: 6, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 6, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 29, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 30, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 5, calendar }).since(end, { largestUnit }),
0, -3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 6, calendar }).since(end, { largestUnit }),
0, -2, 0, -29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDate.from({ year: 1973, monthCode: "M13", day: 5, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).since(end, { largestUnit: "months" }),
0, -40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).since(end, { largestUnit: "years" }),
-3, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 6, calendar }).since(end, { largestUnit: "months" }),
0, -39, 0, -29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 7, calendar }).since(end, { largestUnit: "years" }),
-3, 0, 0, -28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 29, calendar })
.since(Temporal.PlainDate.from({ year: 1970, monthCode: "M03", day: 28, calendar }), { largestUnit: "months" }),
0, -1, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 30, calendar })
.since(Temporal.PlainDate.from({ year: 1971, monthCode: "M05", day: 29, calendar }), { largestUnit: "years" }),
-1, -3, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -94,12 +94,12 @@ const calendar = "gregory";
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 31, calendar }).since(end, { largestUnit: "months" }), Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 31, calendar }).since(end, { largestUnit: "months" }),
0, -27, 0, -30, 0, 0, 0, 0, 0, 0, 0, -27, 0, -30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months" "Dec 31st 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months"
); );
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 31, calendar }).since(end, { largestUnit: "years" }), Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 31, calendar }).since(end, { largestUnit: "years" }),
-2, -3, 0, -30, 0, 0, 0, 0, 0, 0, -2, -3, 0, -30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months" "Dec 31st 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months"
); );
} }

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindate.prototype.until
description: Tests balancing of days to months at end of month (coptic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "coptic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pi Kogi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 28, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pi Kogi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 29, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pi Kogi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 30, calendar }).until(end, { largestUnit }),
0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pi Kogi Enavot (M13)
{
const end = Temporal.PlainDate.from({ year: 1971, monthCode: "M13", day: 6, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 6, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pi Kogi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 29, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pi Kogi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 30, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 5, calendar }).until(end, { largestUnit }),
0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pi Kogi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 6, calendar }).until(end, { largestUnit }),
0, 2, 0, 29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pi Kogi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDate.from({ year: 1973, monthCode: "M13", day: 5, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).until(end, { largestUnit: "months" }),
0, 40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).until(end, { largestUnit: "years" }),
3, 1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 6, calendar }).until(end, { largestUnit: "months" }),
0, 39, 0, 29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pi Kogi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 7, calendar }).until(end, { largestUnit: "years" }),
3, 0, 0, 28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 29, calendar })
.until(Temporal.PlainDate.from({ year: 1970, monthCode: "M03", day: 28, calendar }), { largestUnit: "months" }),
0, 1, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 30, calendar })
.until(Temporal.PlainDate.from({ year: 1971, monthCode: "M05", day: 29, calendar }), { largestUnit: "years" }),
1, 3, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindate.prototype.until
description: Tests balancing of days to months at end of month (ethioaa calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethioaa";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 28, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 29, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 30, calendar }).until(end, { largestUnit }),
0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.PlainDate.from({ year: 1971, monthCode: "M13", day: 6, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 6, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 29, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 30, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 5, calendar }).until(end, { largestUnit }),
0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 6, calendar }).until(end, { largestUnit }),
0, 2, 0, 29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDate.from({ year: 1973, monthCode: "M13", day: 5, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).until(end, { largestUnit: "months" }),
0, 40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).until(end, { largestUnit: "years" }),
3, 1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 6, calendar }).until(end, { largestUnit: "months" }),
0, 39, 0, 29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 7, calendar }).until(end, { largestUnit: "years" }),
3, 0, 0, 28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 29, calendar })
.until(Temporal.PlainDate.from({ year: 1970, monthCode: "M03", day: 28, calendar }), { largestUnit: "months" }),
0, 1, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 30, calendar })
.until(Temporal.PlainDate.from({ year: 1971, monthCode: "M05", day: 29, calendar }), { largestUnit: "years" }),
1, 3, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindate.prototype.until
description: Tests balancing of days to months at end of month (ethiopic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethiopic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 28, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 29, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 30, calendar }).until(end, { largestUnit }),
0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.PlainDate.from({ year: 1971, monthCode: "M13", day: 6, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 6, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 29, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1971, monthCode: "M12", day: 30, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDate.from({ year: 1970, monthCode: "M13", day: 5, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 5, calendar }).until(end, { largestUnit }),
0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M10", day: 6, calendar }).until(end, { largestUnit }),
0, 2, 0, 29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDate.from({ year: 1973, monthCode: "M13", day: 5, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).until(end, { largestUnit: "months" }),
0, 40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 5, calendar }).until(end, { largestUnit: "years" }),
3, 1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 6, calendar }).until(end, { largestUnit: "months" }),
0, 39, 0, 29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 7, calendar }).until(end, { largestUnit: "years" }),
3, 0, 0, 28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 29, calendar })
.until(Temporal.PlainDate.from({ year: 1970, monthCode: "M03", day: 28, calendar }), { largestUnit: "months" }),
0, 1, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M01", day: 30, calendar })
.until(Temporal.PlainDate.from({ year: 1971, monthCode: "M05", day: 29, calendar }), { largestUnit: "years" }),
1, 3, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -94,12 +94,12 @@ const calendar = "gregory";
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 31, calendar }).until(end, { largestUnit: "months" }), Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 31, calendar }).until(end, { largestUnit: "months" }),
0, 27, 0, 30, 0, 0, 0, 0, 0, 0, 0, 27, 0, 30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months" "Dec 31st 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months"
); );
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 31, calendar }).until(end, { largestUnit: "years" }), Temporal.PlainDate.from({ year: 1970, monthCode: "M12", day: 31, calendar }).until(end, { largestUnit: "years" }),
2, 3, 0, 30, 0, 0, 0, 0, 0, 0, 2, 3, 0, 30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months" "Dec 31st 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months"
); );
} }

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindatetime.prototype.since
description: Tests balancing of days to months at end of month (coptic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "coptic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pi Kogi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pi Kogi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pi Kogi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pi Kogi Enavot (M13)
{
const end = Temporal.PlainDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pi Kogi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pi Kogi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pi Kogi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -2, 0, -29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pi Kogi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "months" }),
0, -40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "years" }),
-3, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "months" }),
0, -39, 0, -29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pi Kogi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "years" }),
-3, 0, 0, -28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, calendar })
.since(Temporal.PlainDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, calendar }), { largestUnit: "months" }),
0, -1, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, calendar })
.since(Temporal.PlainDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, calendar }), { largestUnit: "years" }),
-1, -3, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindatetime.prototype.since
description: Tests balancing of days to months at end of month (ethioaa calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethioaa";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.PlainDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -2, 0, -29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "months" }),
0, -40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "years" }),
-3, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "months" }),
0, -39, 0, -29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "years" }),
-3, 0, 0, -28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, calendar })
.since(Temporal.PlainDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, calendar }), { largestUnit: "months" }),
0, -1, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, calendar })
.since(Temporal.PlainDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, calendar }), { largestUnit: "years" }),
-1, -3, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindatetime.prototype.since
description: Tests balancing of days to months at end of month (ethiopic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethiopic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.PlainDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, calendar }).since(end, { largestUnit }),
0, -2, 0, -29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "months" }),
0, -40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "years" }),
-3, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "months" }),
0, -39, 0, -29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "years" }),
-3, 0, 0, -28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, calendar })
.since(Temporal.PlainDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, calendar }), { largestUnit: "months" }),
0, -1, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, calendar })
.since(Temporal.PlainDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, calendar }), { largestUnit: "years" }),
-1, -3, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -94,12 +94,12 @@ const calendar = "gregory";
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "months" }), Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "months" }),
0, -27, 0, -30, 0, 0, 0, 0, 0, 0, 0, -27, 0, -30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months" "Dec 31st 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months"
); );
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "years" }), Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, calendar }).since(end, { largestUnit: "years" }),
-2, -3, 0, -30, 0, 0, 0, 0, 0, 0, -2, -3, 0, -30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months" "Dec 31st 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months"
); );
} }

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindatetime.prototype.until
description: Tests balancing of days to months at end of month (coptic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "coptic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pi Kogi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pi Kogi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pi Kogi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pi Kogi Enavot (M13)
{
const end = Temporal.PlainDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pi Kogi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pi Kogi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pi Kogi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 2, 0, 29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pi Kogi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "months" }),
0, 40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "years" }),
3, 1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "months" }),
0, 39, 0, 29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pi Kogi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "years" }),
3, 0, 0, 28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, calendar })
.until(Temporal.PlainDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, calendar }), { largestUnit: "months" }),
0, 1, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, calendar })
.until(Temporal.PlainDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, calendar }), { largestUnit: "years" }),
1, 3, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindatetime.prototype.until
description: Tests balancing of days to months at end of month (ethioaa calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethioaa";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.PlainDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 2, 0, 29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "months" }),
0, 40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "years" }),
3, 1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "months" }),
0, 39, 0, 29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "years" }),
3, 0, 0, 28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, calendar })
.until(Temporal.PlainDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, calendar }), { largestUnit: "months" }),
0, 1, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, calendar })
.until(Temporal.PlainDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, calendar }), { largestUnit: "years" }),
1, 3, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.plaindatetime.prototype.until
description: Tests balancing of days to months at end of month (ethiopic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethiopic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.PlainDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.PlainDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, calendar }).until(end, { largestUnit }),
0, 2, 0, 29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.PlainDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, calendar });
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "months" }),
0, 40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "years" }),
3, 1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "months" }),
0, 39, 0, 29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "years" }),
3, 0, 0, 28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, calendar })
.until(Temporal.PlainDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, calendar }), { largestUnit: "months" }),
0, 1, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, calendar })
.until(Temporal.PlainDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, calendar }), { largestUnit: "years" }),
1, 3, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -94,12 +94,12 @@ const calendar = "gregory";
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "months" }), Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "months" }),
0, 27, 0, 30, 0, 0, 0, 0, 0, 0, 0, 27, 0, 30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months" "Dec 31st 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months"
); );
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "years" }), Temporal.PlainDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, calendar }).until(end, { largestUnit: "years" }),
2, 3, 0, 30, 0, 0, 0, 0, 0, 0, 2, 3, 0, 30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months" "Dec 31st 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months"
); );
} }

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.zoneddatetime.prototype.since
description: Tests balancing of days to months at end of month (coptic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "coptic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pi Kogi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pi Kogi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pi Kogi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pi Kogi Enavot (M13)
{
const end = Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pi Kogi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pi Kogi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pi Kogi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -2, 0, -29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pi Kogi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.ZonedDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "months" }),
0, -40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "years" }),
-3, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "months" }),
0, -39, 0, -29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pi Kogi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "years" }),
-3, 0, 0, -28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar })
.since(Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "months" }),
0, -1, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar })
.since(Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "years" }),
-1, -3, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.zoneddatetime.prototype.since
description: Tests balancing of days to months at end of month (ethioaa calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethioaa";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -2, 0, -29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.ZonedDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "months" }),
0, -40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "years" }),
-3, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "months" }),
0, -39, 0, -29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "years" }),
-3, 0, 0, -28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar })
.since(Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "months" }),
0, -1, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar })
.since(Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "years" }),
-1, -3, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.zoneddatetime.prototype.since
description: Tests balancing of days to months at end of month (ethiopic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethiopic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, 0, 0, -6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit }),
0, -2, 0, -29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.ZonedDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "months" }),
0, -40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "years" }),
-3, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "months" }),
0, -39, 0, -29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "years" }),
-3, 0, 0, -28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar })
.since(Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "months" }),
0, -1, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar })
.since(Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "years" }),
-1, -3, 0, -29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -94,12 +94,12 @@ const calendar = "gregory";
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "months" }), Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "months" }),
0, -27, 0, -30, 0, 0, 0, 0, 0, 0, 0, -27, 0, -30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months" "Dec 31st 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months"
); );
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "years" }), Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, timeZone: "UTC", calendar }).since(end, { largestUnit: "years" }),
-2, -3, 0, -30, 0, 0, 0, 0, 0, 0, -2, -3, 0, -30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months" "Dec 31st 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months"
); );
} }

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.zoneddatetime.prototype.until
description: Tests balancing of days to months at end of month (coptic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "coptic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pi Kogi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pi Kogi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pi Kogi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pi Kogi Enavot (M13)
{
const end = Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pi Kogi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pi Kogi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pi Kogi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pi Kogi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 2, 0, 29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pi Kogi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.ZonedDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "months" }),
0, 40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "years" }),
3, 1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "months" }),
0, 39, 0, 29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pi Kogi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "years" }),
3, 0, 0, 28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pi Kogi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar })
.until(Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "months" }),
0, 1, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar })
.until(Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "years" }),
1, 3, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.zoneddatetime.prototype.until
description: Tests balancing of days to months at end of month (ethioaa calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethioaa";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 2, 0, 29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.ZonedDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "months" }),
0, 40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "years" }),
3, 1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "months" }),
0, 39, 0, 29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "years" }),
3, 0, 0, 28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar })
.until(Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "months" }),
0, 1, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar })
.until(Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "years" }),
1, 3, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -0,0 +1,121 @@
// Copyright (C) 2025 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal.zoneddatetime.prototype.until
description: Tests balancing of days to months at end of month (ethiopic calendar)
includes: [temporalHelpers.js]
features: [Temporal, Intl.Era-monthcode]
---*/
const calendar = "ethiopic";
// Difference between end of longer month to end of following shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 5th to Pikougi Enavot 5th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 28th to Pikougi Enavot 5th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 29th to Pikougi Enavot 5th is 6 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 5th is 5 days, not one month (${largestUnit})`
);
}
}
// Difference between end of leap-year Mesori (M12) to end of leap-year Pikougi Enavot (M13)
{
const end = Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M13", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
`Mesori 6th to Pikougi Enavot 6th is one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 7, 0, 0, 0, 0, 0, 0,
`Mesori 31st to Pikougi Enavot 6th is 7 days, not one month (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M12", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 0, 0, 6, 0, 0, 0, 0, 0, 0,
`Mesori 30th to Pikougi Enavot 6th is 6 days, not one month (${largestUnit})`
);
}
}
// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
`Paoni 5th to Pikougi Enavot 5th is 3 months (${largestUnit})`
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M10", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit }),
0, 2, 0, 29, 0, 0, 0, 0, 0, 0,
`Paoni 6th to Pikougi Enavot 5th is 2 months 29 days, not 3 months (${largestUnit})`
);
}
}
// Difference between end of longer month in one year to shorter month in
// later year
{
const end = Temporal.ZonedDateTime.from({ year: 1973, monthCode: "M13", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar });
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "months" }),
0, 40, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 5, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "years" }),
3, 1, 0, 0, 0, 0, 0, 0, 0, 0,
"Mesori 5th 1970 to Pikougi Enavot 5th 1973 is 3 years, 1 month"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 6, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "months" }),
0, 39, 0, 29, 0, 0, 0, 0, 0, 0,
"Mesori 6th 1970 to Pikougi Enavot 5th 1973 is 39 months, 29 days, not 40 months"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 7, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "years" }),
3, 0, 0, 28, 0, 0, 0, 0, 0, 0,
"Mesori 7th 1970 to Pikougi Enavot 5th 1973 is 3 years, 28 days"
);
}
// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar })
.until(Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M03", day: 28, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "months" }),
0, 1, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 29th to Hathor 28th is 1 month 29 days, not 59 days"
);
TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M01", day: 30, hour: 12, minute: 34, timeZone: "UTC", calendar })
.until(Temporal.ZonedDateTime.from({ year: 1971, monthCode: "M05", day: 29, hour: 12, minute: 34, timeZone: "UTC", calendar }), { largestUnit: "years" }),
1, 3, 0, 29, 0, 0, 0, 0, 0, 0,
"Thout 30th 1970 to Tobi 29th 1971 is 1 year, 3 months, 29 days, not 1 year, 2 months, 59 days"
);
}

View File

@ -94,12 +94,12 @@ const calendar = "gregory";
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "months" }), Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "months" }),
0, 27, 0, 30, 0, 0, 0, 0, 0, 0, 0, 27, 0, 30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months" "Dec 31st 1970 to Apr 30th 1973 is 27 months, 30 days, not 28 months"
); );
TemporalHelpers.assertDuration( TemporalHelpers.assertDuration(
Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "years" }), Temporal.ZonedDateTime.from({ year: 1970, monthCode: "M12", day: 31, hour: 12, minute: 34, timeZone: "UTC", calendar }).until(end, { largestUnit: "years" }),
2, 3, 0, 30, 0, 0, 0, 0, 0, 0, 2, 3, 0, 30, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months" "Dec 31st 1970 to Apr 30th 1973 is 2 years, 3 months, 30 days, not 2 years 4 months"
); );
} }