From 49e56acc67ae0b18ea8d06784559230e4a024b65 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Fri, 26 Jan 2024 17:25:52 -0800 Subject: [PATCH] Temporal: Tests for date difference algorithm 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: https://github.com/tc39/proposal-temporal/pull/2759 Consensus in February 2024 --- .../since/wrapping-at-end-of-month.js | 117 ++++++++++++++++++ .../until/largestunit-higher-units.js | 10 +- .../until/wrapping-at-end-of-month.js | 117 ++++++++++++++++++ .../since/wrapping-at-end-of-month.js | 117 ++++++++++++++++++ .../prototype/until/no-unnecessary-units.js | 8 +- .../until/wrapping-at-end-of-month.js | 117 ++++++++++++++++++ .../since/wrapping-at-end-of-month.js | 117 ++++++++++++++++++ .../until/wrapping-at-end-of-month.js | 117 ++++++++++++++++++ 8 files changed, 711 insertions(+), 9 deletions(-) create mode 100644 test/built-ins/Temporal/PlainDate/prototype/since/wrapping-at-end-of-month.js create mode 100644 test/built-ins/Temporal/PlainDate/prototype/until/wrapping-at-end-of-month.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/since/wrapping-at-end-of-month.js create mode 100644 test/built-ins/Temporal/PlainDateTime/prototype/until/wrapping-at-end-of-month.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/since/wrapping-at-end-of-month.js create mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/until/wrapping-at-end-of-month.js diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/wrapping-at-end-of-month.js b/test/built-ins/Temporal/PlainDate/prototype/since/wrapping-at-end-of-month.js new file mode 100644 index 0000000000..6e0d8c4ac4 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/since/wrapping-at-end-of-month.js @@ -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" + ); +} diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js b/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js index 30fd70ae2a..37927cab1d 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/largestunit-higher-units.js @@ -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"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/wrapping-at-end-of-month.js b/test/built-ins/Temporal/PlainDate/prototype/until/wrapping-at-end-of-month.js new file mode 100644 index 0000000000..1ec9e169f4 --- /dev/null +++ b/test/built-ins/Temporal/PlainDate/prototype/until/wrapping-at-end-of-month.js @@ -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" + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/since/wrapping-at-end-of-month.js b/test/built-ins/Temporal/PlainDateTime/prototype/since/wrapping-at-end-of-month.js new file mode 100644 index 0000000000..2c07323c55 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/since/wrapping-at-end-of-month.js @@ -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" + ); +} diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js index 081f9502ef..92da609fc7 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/no-unnecessary-units.js @@ -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)" ); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/wrapping-at-end-of-month.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/wrapping-at-end-of-month.js new file mode 100644 index 0000000000..fa534d6020 --- /dev/null +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/wrapping-at-end-of-month.js @@ -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.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.PlainDateTime(1970, 2, 28); + for (const largestUnit of ["years", "months"]) { + TemporalHelpers.assertDuration( + new Temporal.PlainDateTime(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.PlainDateTime(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.PlainDateTime(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.PlainDateTime(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.PlainDateTime(1972, 2, 29); + for (const largestUnit of ["years", "months"]) { + TemporalHelpers.assertDuration( + new Temporal.PlainDateTime(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.PlainDateTime(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.PlainDateTime(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.PlainDateTime(1970, 11, 30); + for (const largestUnit of ["years", "months"]) { + TemporalHelpers.assertDuration( + new Temporal.PlainDateTime(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.PlainDateTime(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.PlainDateTime(1973, 4, 30); + TemporalHelpers.assertDuration( + new Temporal.PlainDateTime(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.PlainDateTime(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.PlainDateTime(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.PlainDateTime(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.PlainDateTime(1970, 1, 29).until(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).until(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" + ); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/wrapping-at-end-of-month.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/wrapping-at-end-of-month.js new file mode 100644 index 0000000000..1cbc894d49 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/wrapping-at-end-of-month.js @@ -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.zoneddatetime.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.ZonedDateTime(5011200_000_000_000n /* = 1970-02-28T00Z */, "UTC"); + for (const largestUnit of ["years", "months"]) { + TemporalHelpers.assertDuration( + new Temporal.ZonedDateTime(2332800_000_000_000n /* = 1970-01-28T00Z */, "UTC").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.ZonedDateTime(2419200_000_000_000n /* = 1970-01-29T00Z */, "UTC").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.ZonedDateTime(2505600_000_000_000n /* = 1970-01-30T00Z */, "UTC").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.ZonedDateTime(2592000_000_000_000n /* = 1970-01-31T00Z */, "UTC").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.ZonedDateTime(68169600_000_000_000n /* = 1972-02-29T00Z */, "UTC"); + for (const largestUnit of ["years", "months"]) { + TemporalHelpers.assertDuration( + new Temporal.ZonedDateTime(65491200_000_000_000n /* = 1972-01-29T00Z */, "UTC").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.ZonedDateTime(65577600_000_000_000n /* = 1972-01-30T00Z */, "UTC").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.ZonedDateTime(65664000_000_000_000n /* = 1972-01-31T00Z */, "UTC").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.ZonedDateTime(28771200_000_000_000n /* = 1970-11-30T00Z */, "UTC"); + for (const largestUnit of ["years", "months"]) { + TemporalHelpers.assertDuration( + new Temporal.ZonedDateTime(20822400_000_000_000n /* = 1970-08-30T00Z */, "UTC").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.ZonedDateTime(20908800_000_000_000n /* = 1970-08-31T00Z */, "UTC").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.ZonedDateTime(104976000_000_000_000n /* = 1973-04-30T00Z */, "UTC"); + TemporalHelpers.assertDuration( + new Temporal.ZonedDateTime(31363200_000_000_000n /* = 1970-12-30T00Z */, "UTC").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.ZonedDateTime(31363200_000_000_000n /* = 1970-12-30T00Z */, "UTC").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.ZonedDateTime(31449600_000_000_000n /* = 1970-12-31T00Z */, "UTC").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.ZonedDateTime(31449600_000_000_000n /* = 1970-12-31T00Z */, "UTC").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.ZonedDateTime(2419200_000_000_000n /* = 1970-01-29T00Z */, "UTC").since(new Temporal.ZonedDateTime(7430400_000_000_000n /* = 1970-03-28T00Z */, "UTC"), { 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.ZonedDateTime(2592000_000_000_000n /* = 1970-01-31T00Z */, "UTC").since(new Temporal.ZonedDateTime(44409600_000_000_000n /* = 1971-05-30T00Z */, "UTC"), { 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" + ); +} diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/wrapping-at-end-of-month.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/wrapping-at-end-of-month.js new file mode 100644 index 0000000000..e84b82f1b2 --- /dev/null +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/wrapping-at-end-of-month.js @@ -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.zoneddatetime.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.ZonedDateTime(5011200_000_000_000n /* = 1970-02-28T00Z */, "UTC"); + for (const largestUnit of ["years", "months"]) { + TemporalHelpers.assertDuration( + new Temporal.ZonedDateTime(2332800_000_000_000n /* = 1970-01-28T00Z */, "UTC").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.ZonedDateTime(2419200_000_000_000n /* = 1970-01-29T00Z */, "UTC").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.ZonedDateTime(2505600_000_000_000n /* = 1970-01-30T00Z */, "UTC").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.ZonedDateTime(2592000_000_000_000n /* = 1970-01-31T00Z */, "UTC").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.ZonedDateTime(68169600_000_000_000n /* = 1972-02-29T00Z */, "UTC"); + for (const largestUnit of ["years", "months"]) { + TemporalHelpers.assertDuration( + new Temporal.ZonedDateTime(65491200_000_000_000n /* = 1972-01-29T00Z */, "UTC").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.ZonedDateTime(65577600_000_000_000n /* = 1972-01-30T00Z */, "UTC").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.ZonedDateTime(65664000_000_000_000n /* = 1972-01-31T00Z */, "UTC").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.ZonedDateTime(28771200_000_000_000n /* = 1970-11-30T00Z */, "UTC"); + for (const largestUnit of ["years", "months"]) { + TemporalHelpers.assertDuration( + new Temporal.ZonedDateTime(20822400_000_000_000n /* = 1970-08-30T00Z */, "UTC").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.ZonedDateTime(20908800_000_000_000n /* = 1970-08-31T00Z */, "UTC").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.ZonedDateTime(104976000_000_000_000n /* = 1973-04-30T00Z */, "UTC"); + TemporalHelpers.assertDuration( + new Temporal.ZonedDateTime(31363200_000_000_000n /* = 1970-12-30T00Z */, "UTC").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.ZonedDateTime(31363200_000_000_000n /* = 1970-12-30T00Z */, "UTC").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.ZonedDateTime(31449600_000_000_000n /* = 1970-12-31T00Z */, "UTC").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.ZonedDateTime(31449600_000_000_000n /* = 1970-12-31T00Z */, "UTC").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.ZonedDateTime(2419200_000_000_000n /* = 1970-01-29T00Z */, "UTC").until(new Temporal.ZonedDateTime(7430400_000_000_000n /* = 1970-03-28T00Z */, "UTC"), { 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.ZonedDateTime(2592000_000_000_000n /* = 1970-01-31T00Z */, "UTC").until(new Temporal.ZonedDateTime(44409600_000_000_000n /* = 1971-05-30T00Z */, "UTC"), { 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" + ); +}