Skip to content

Commit

Permalink
Temporal: Tests for date difference algorithm
Browse files Browse the repository at this point in the history
This adds tests specifically for every kind of case that changes due to
the tweak to the date difference algorithm: differences from a longer
month to a shorter month, when the months are adjacent, in the same year
but not adjacent, and in different years.

Also adds tests for a case that does *not* change, but would trip on an
incorrectly implemented algorithm: when the intermediate months value
falls at the end of February.

There was incidental coverage of the change to the date difference
algorithm in other tests. Those are adjusted, as well.

Normative change: tc39/proposal-temporal#2759
Consensus in February 2024
  • Loading branch information
ptomato committed Feb 10, 2024
1 parent f742eb0 commit 49e56ac
Show file tree
Hide file tree
Showing 8 changed files with 711 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (C) 2024 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
includes: [temporalHelpers.js]
features: [Temporal]
---*/

// Difference between end of longer month to end of following shorter month
{
const end = new Temporal.PlainDate(1970, 2, 28);
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 28).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Jan 28th to Feb 28th is one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 29).since(end, { largestUnit }),
0, 0, 0, -30, 0, 0, 0, 0, 0, 0,
"Jan 29th to Feb 28th is 30 days, not one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 30).since(end, { largestUnit }),
0, 0, 0, -29, 0, 0, 0, 0, 0, 0,
"Jan 30th to Feb 28th is 29 days, not one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 31).since(end, { largestUnit }),
0, 0, 0, -28, 0, 0, 0, 0, 0, 0,
"Jan 31st to Feb 28th is 28 days, not one month"
);
}
}

// Difference between end of leap-year January to end of leap-year February
{
const end = new Temporal.PlainDate(1972, 2, 29);
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1972, 1, 29).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Jan 29th to Feb 29th is one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1972, 1, 30).since(end, { largestUnit }),
0, 0, 0, -30, 0, 0, 0, 0, 0, 0,
"Jan 30th to Feb 29th is 30 days, not one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1972, 1, 31).since(end, { largestUnit }),
0, 0, 0, -29, 0, 0, 0, 0, 0, 0,
"Jan 31st to Feb 29th is 29 days, not one month"
);
}
}

// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = new Temporal.PlainDate(1970, 11, 30);
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 8, 30).since(end, { largestUnit }),
0, -3, 0, 0, 0, 0, 0, 0, 0, 0,
"Aug 30th to Nov 30th is 3 months"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 8, 31).since(end, { largestUnit }),
0, -2, 0, -30, 0, 0, 0, 0, 0, 0,
"Aug 31st to Nov 30th is 2 months 30 days, not 3 months"
);
}
}

// Difference between end of longer month in one year to shorter month in
// later year
{
const end = new Temporal.PlainDate(1973, 4, 30);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 12, 30).since(end, { largestUnit: "months" }),
0, -28, 0, 0, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 28 months"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 12, 30).since(end, { largestUnit: "years" }),
-2, -4, 0, 0, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 2 years, 4 months"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 12, 31).since(end, { largestUnit: "months" }),
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"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 12, 31).since(end, { largestUnit: "years" }),
-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"
);
}

// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 29).since(new Temporal.PlainDate(1970, 3, 28), { largestUnit: "months" }),
0, -1, 0, -28, 0, 0, 0, 0, 0, 0,
"Jan 29th to Mar 28th is 1 month 28 days, not 58 days"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 31).since(new Temporal.PlainDate(1971, 5, 30), { largestUnit: "years" }),
-1, -3, 0, -30, 0, 0, 0, 0, 0, 0,
"Jan 31st 1970 to May 30th 1971 is 1 year, 3 months, 30 days, not 1 year, 2 months, 60 days"
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "years" }), /*
TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "months" }), 0, /* months = */ 12, 0, 0, 0, 0, 0, 0, 0, 0, "start of February, months");
TemporalHelpers.assertDuration(feb20.until(feb21, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 2, 0, 0, 0, 0, 0, 0, "start of February, weeks");

const lastFeb20 = Temporal.PlainDate.from("2020-02-29");
const lastFeb21 = Temporal.PlainDate.from("2021-02-28");
TemporalHelpers.assertDuration(lastFeb20.until(lastFeb21, { largestUnit: "years" }), /* years = */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "end of February, years");
TemporalHelpers.assertDuration(lastFeb20.until(lastFeb21, { largestUnit: "months" }), 0, /* months = */ 12, 0, 0, 0, 0, 0, 0, 0, 0, "end of February, months");
TemporalHelpers.assertDuration(lastFeb20.until(lastFeb21, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 1, 0, 0, 0, 0, 0, 0, "end of February, weeks");
const lastFeb21 = new Temporal.PlainDate(2021, 2, 28);
const lastFeb22 = new Temporal.PlainDate(2022, 2, 28);
TemporalHelpers.assertDuration(lastFeb21.until(lastFeb22, { largestUnit: "years" }), /* years = */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, "end of February, years");
TemporalHelpers.assertDuration(lastFeb21.until(lastFeb22, { largestUnit: "months" }), 0, /* months = */ 12, 0, 0, 0, 0, 0, 0, 0, 0, "end of February, months");
TemporalHelpers.assertDuration(lastFeb21.until(lastFeb22, { largestUnit: "weeks" }), 0, 0, /* weeks = */ 52, /* days = */ 1, 0, 0, 0, 0, 0, 0, "end of February, weeks");
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (C) 2024 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
includes: [temporalHelpers.js]
features: [Temporal]
---*/

// Difference between end of longer month to end of following shorter month
{
const end = new Temporal.PlainDate(1970, 2, 28);
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 28).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
"Jan 28th to Feb 28th is one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 29).until(end, { largestUnit }),
0, 0, 0, 30, 0, 0, 0, 0, 0, 0,
"Jan 29th to Feb 28th is 30 days, not one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 30).until(end, { largestUnit }),
0, 0, 0, 29, 0, 0, 0, 0, 0, 0,
"Jan 30th to Feb 28th is 29 days, not one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 31).until(end, { largestUnit }),
0, 0, 0, 28, 0, 0, 0, 0, 0, 0,
"Jan 31st to Feb 28th is 28 days, not one month"
);
}
}

// Difference between end of leap-year January to end of leap-year February
{
const end = new Temporal.PlainDate(1972, 2, 29);
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1972, 1, 29).until(end, { largestUnit }),
0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
"Jan 29th to Feb 29th is one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1972, 1, 30).until(end, { largestUnit }),
0, 0, 0, 30, 0, 0, 0, 0, 0, 0,
"Jan 30th to Feb 29th is 30 days, not one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1972, 1, 31).until(end, { largestUnit }),
0, 0, 0, 29, 0, 0, 0, 0, 0, 0,
"Jan 31st to Feb 29th is 29 days, not one month"
);
}
}

// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = new Temporal.PlainDate(1970, 11, 30);
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 8, 30).until(end, { largestUnit }),
0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
"Aug 30th to Nov 30th is 3 months"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 8, 31).until(end, { largestUnit }),
0, 2, 0, 30, 0, 0, 0, 0, 0, 0,
"Aug 31st to Nov 30th is 2 months 30 days, not 3 months"
);
}
}

// Difference between end of longer month in one year to shorter month in
// later year
{
const end = new Temporal.PlainDate(1973, 4, 30);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 12, 30).until(end, { largestUnit: "months" }),
0, 28, 0, 0, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 28 months"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 12, 30).until(end, { largestUnit: "years" }),
2, 4, 0, 0, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 2 years, 4 months"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 12, 31).until(end, { largestUnit: "months" }),
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"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 12, 31).until(end, { largestUnit: "years" }),
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"
);
}

// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 29).until(new Temporal.PlainDate(1970, 3, 28), { largestUnit: "months" }),
0, 1, 0, 28, 0, 0, 0, 0, 0, 0,
"Jan 29th to Mar 28th is 1 month 28 days, not 58 days"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDate(1970, 1, 31).until(new Temporal.PlainDate(1971, 5, 30), { largestUnit: "years" }),
1, 3, 0, 30, 0, 0, 0, 0, 0, 0,
"Jan 31st 1970 to May 30th 1971 is 1 year, 3 months, 30 days, not 1 year, 2 months, 60 days"
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (C) 2024 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
includes: [temporalHelpers.js]
features: [Temporal]
---*/

// Difference between end of longer month to end of following shorter month
{
const end = new Temporal.PlainDateTime(1970, 2, 28);
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 1, 28).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Jan 28th to Feb 28th is one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 1, 29).since(end, { largestUnit }),
0, 0, 0, -30, 0, 0, 0, 0, 0, 0,
"Jan 29th to Feb 28th is 30 days, not one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 1, 30).since(end, { largestUnit }),
0, 0, 0, -29, 0, 0, 0, 0, 0, 0,
"Jan 30th to Feb 28th is 29 days, not one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 1, 31).since(end, { largestUnit }),
0, 0, 0, -28, 0, 0, 0, 0, 0, 0,
"Jan 31st to Feb 28th is 28 days, not one month"
);
}
}

// Difference between end of leap-year January to end of leap-year February
{
const end = new Temporal.PlainDateTime(1972, 2, 29);
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1972, 1, 29).since(end, { largestUnit }),
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
"Jan 29th to Feb 29th is one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1972, 1, 30).since(end, { largestUnit }),
0, 0, 0, -30, 0, 0, 0, 0, 0, 0,
"Jan 30th to Feb 29th is 30 days, not one month"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1972, 1, 31).since(end, { largestUnit }),
0, 0, 0, -29, 0, 0, 0, 0, 0, 0,
"Jan 31st to Feb 29th is 29 days, not one month"
);
}
}

// Difference between end of longer month to end of not-immediately-following
// shorter month
{
const end = new Temporal.PlainDateTime(1970, 11, 30);
for (const largestUnit of ["years", "months"]) {
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 8, 30).since(end, { largestUnit }),
0, -3, 0, 0, 0, 0, 0, 0, 0, 0,
"Aug 30th to Nov 30th is 3 months"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 8, 31).since(end, { largestUnit }),
0, -2, 0, -30, 0, 0, 0, 0, 0, 0,
"Aug 31st to Nov 30th is 2 months 30 days, not 3 months"
);
}
}

// Difference between end of longer month in one year to shorter month in
// later year
{
const end = new Temporal.PlainDateTime(1973, 4, 30);
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 12, 30).since(end, { largestUnit: "months" }),
0, -28, 0, 0, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 28 months"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 12, 30).since(end, { largestUnit: "years" }),
-2, -4, 0, 0, 0, 0, 0, 0, 0, 0,
"Dec 30th 1970 to Apr 30th 1973 is 2 years, 4 months"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 12, 31).since(end, { largestUnit: "months" }),
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"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 12, 31).since(end, { largestUnit: "years" }),
-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"
);
}

// Difference where months passes through a month that's the same length or
// shorter than either the start or end month
{
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 1, 29).since(new Temporal.PlainDateTime(1970, 3, 28), { largestUnit: "months" }),
0, -1, 0, -28, 0, 0, 0, 0, 0, 0,
"Jan 29th to Mar 28th is 1 month 28 days, not 58 days"
);
TemporalHelpers.assertDuration(
new Temporal.PlainDateTime(1970, 1, 31).since(new Temporal.PlainDateTime(1971, 5, 30), { largestUnit: "years" }),
-1, -3, 0, -30, 0, 0, 0, 0, 0, 0,
"Jan 31st 1970 to May 30th 1971 is 1 year, 3 months, 30 days, not 1 year, 2 months, 60 days"
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ features: [Temporal]
includes: [temporalHelpers.js]
---*/

const feb29 = new Temporal.PlainDateTime(2020, 2, 29, 0, 0);
const feb28 = new Temporal.PlainDateTime(2021, 2, 28, 0, 0);
const lastFeb21 = new Temporal.PlainDateTime(2021, 2, 28);
const lastFeb22 = new Temporal.PlainDateTime(2022, 2, 28);

TemporalHelpers.assertDuration(
feb29.until(feb28, { largestUnit: "months" }),
lastFeb21.until(lastFeb22, { largestUnit: "months" }),
0, 12, 0, 0, 0, 0, 0, 0, 0, 0,
"does not include higher units than necessary (largest unit = months)"
);

TemporalHelpers.assertDuration(
feb29.until(feb28, { largestUnit: "years" }),
lastFeb21.until(lastFeb22, { largestUnit: "years" }),
1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
"does not include higher units than necessary (largest unit = years)"
);
Loading

0 comments on commit 49e56ac

Please sign in to comment.