Skip to content

Commit ebbb423

Browse files
committed
Intl Era Monthcode: Add coverage for lunisolar wrapping at end of month
See tc39/proposal-intl-era-monthcode#101 This normative change was actually already reflected in the tests by mistake, so those "broken" tests are now rendered correct. However, I've also expanded the existing tests and added some more edge cases. The Hebrew calendar was not yet covered at all (pending this issue) so I've added new test files for that as well.
1 parent 3c6180f commit ebbb423

18 files changed

+2244
-168
lines changed

test/intl402/Temporal/PlainDate/prototype/since/wrapping-at-end-of-month-chinese.js

Lines changed: 100 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@ features: [Temporal, Intl.Era-monthcode]
99
---*/
1010

1111
const calendar = "chinese";
12+
const options = { overflow: "reject" };
1213

1314
// Difference between end of 30-day month to end of following 29-day month
1415
{
15-
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M06", day: 29, calendar });
16+
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M06", day: 29, calendar }, options);
1617
for (const largestUnit of ["years", "months"]) {
1718
TemporalHelpers.assertDuration(
18-
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 29, calendar }).since(end, { largestUnit }),
19+
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 29, calendar }, options).since(end, { largestUnit }),
1920
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
2021
`M05-29 (30d) to M06-29 (29d) is one month (${largestUnit})`
2122
);
2223
TemporalHelpers.assertDuration(
23-
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 30, calendar }).since(end, { largestUnit }),
24+
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 30, calendar }, options).since(end, { largestUnit }),
2425
0, 0, 0, -29, 0, 0, 0, 0, 0, 0,
2526
`M05-30 to M06-29 is 29 days, not one month (${largestUnit})`
2627
);
@@ -29,15 +30,15 @@ const calendar = "chinese";
2930

3031
// Difference between end of 30-day M04 to end of 29-day M04L
3132
{
32-
const end = Temporal.PlainDate.from({ year: 2020, monthCode: "M04L", day: 29, calendar });
33+
const end = Temporal.PlainDate.from({ year: 2020, monthCode: "M04L", day: 29, calendar }, options);
3334
for (const largestUnit of ["years", "months"]) {
3435
TemporalHelpers.assertDuration(
35-
Temporal.PlainDate.from({ year: 2020, monthCode: "M04", day: 29, calendar }).since(end, { largestUnit }),
36+
Temporal.PlainDate.from({ year: 2020, monthCode: "M04", day: 29, calendar }, options).since(end, { largestUnit }),
3637
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
3738
`M04-29 (30d) to M04L-29 (29d) is one month (${largestUnit})`
3839
);
3940
TemporalHelpers.assertDuration(
40-
Temporal.PlainDate.from({ year: 2020, monthCode: "M04", day: 30, calendar }).since(end, { largestUnit }),
41+
Temporal.PlainDate.from({ year: 2020, monthCode: "M04", day: 30, calendar }, options).since(end, { largestUnit }),
4142
0, 0, 0, -29, 0, 0, 0, 0, 0, 0,
4243
`M04-30 to M04L-29 (29d) is 29 days, not one month (${largestUnit})`
4344
);
@@ -47,15 +48,15 @@ const calendar = "chinese";
4748
// Difference between end of 30-day month to end of not-immediately-following
4849
// 29-day month
4950
{
50-
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M09", day: 29, calendar });
51+
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M09", day: 29, calendar }, options);
5152
for (const largestUnit of ["years", "months"]) {
5253
TemporalHelpers.assertDuration(
53-
Temporal.PlainDate.from({ year: 2023, monthCode: "M04", day: 29, calendar }).since(end, { largestUnit }),
54+
Temporal.PlainDate.from({ year: 2023, monthCode: "M04", day: 29, calendar }, options).since(end, { largestUnit }),
5455
0, -5, 0, 0, 0, 0, 0, 0, 0, 0,
5556
`M04-29 (30d) to M09-29 (29d) is 5 months (${largestUnit})`
5657
);
5758
TemporalHelpers.assertDuration(
58-
Temporal.PlainDate.from({ year: 2023, monthCode: "M04", day: 30, calendar }).since(end, { largestUnit }),
59+
Temporal.PlainDate.from({ year: 2023, monthCode: "M04", day: 30, calendar }, options).since(end, { largestUnit }),
5960
0, -4, 0, -29, 0, 0, 0, 0, 0, 0,
6061
`M04-30 to M09-29 (29d) is 4 months 29 days, not 5 months (${largestUnit})`
6162
);
@@ -65,25 +66,110 @@ const calendar = "chinese";
6566
// Difference between end of 30-day month in one year to 29-day month in later
6667
// year
6768
{
68-
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M09", day: 29, calendar });
69+
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M09", day: 29, calendar }, options);
70+
const start1 = Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 29, calendar }, options);
71+
const start2 = Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 30, calendar }, options);
6972
TemporalHelpers.assertDuration(
70-
Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 29, calendar }).since(end, { largestUnit: "months" }),
73+
start1.since(end, { largestUnit: "months" }),
7174
0, -29, 0, 0, 0, 0, 0, 0, 0, 0,
7275
"2021-M05-29 (30d) to 2023-M09-29 (29d) is 29 days"
7376
);
7477
TemporalHelpers.assertDuration(
75-
Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 29, calendar }).since(end, { largestUnit: "years" }),
78+
start1.since(end, { largestUnit: "years" }),
7679
-2, -4, 0, 0, 0, 0, 0, 0, 0, 0,
7780
"2021-M05-29 (30d) to 2023-M09-29 (29d) is 2 years, 4 months"
7881
);
7982
TemporalHelpers.assertDuration(
80-
Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 30, calendar }).since(end, { largestUnit: "months" }),
83+
start2.since(end, { largestUnit: "months" }),
8184
0, -28, 0, -29, 0, 0, 0, 0, 0, 0,
8285
"2021-M05-30 to 2023-M09-29 (29d) is 28 months, 29 days, not 29 months"
8386
);
8487
TemporalHelpers.assertDuration(
85-
Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 30, calendar }).since(end, { largestUnit: "years" }),
88+
start2.since(end, { largestUnit: "years" }),
8689
-2, -3, 0, -29, 0, 0, 0, 0, 0, 0,
8790
"2021-M05-30 to 2023-M09-29 (29d) is 2 years, 3 months, 29 days, not 2 years 4 months"
8891
);
8992
}
93+
94+
// Difference between end of 30-day common month and end of the same month with
95+
// 29 days in a later year
96+
{
97+
const end = Temporal.PlainDate.from({ year: 2019, monthCode: "M02", day: 29, calendar }, options);
98+
const start1 = Temporal.PlainDate.from({ year: 2018, monthCode: "M02", day: 29, calendar }, options);
99+
const start2 = Temporal.PlainDate.from({ year: 2018, monthCode: "M02", day: 30, calendar }, options);
100+
TemporalHelpers.assertDuration(
101+
start1.since(end, { largestUnit: "months" }),
102+
0, -12, 0, 0, 0, 0, 0, 0, 0, 0,
103+
"2018-M02-29 to 2019-M02-29 is 12 months"
104+
);
105+
TemporalHelpers.assertDuration(
106+
start1.since(end, { largestUnit: "years" }),
107+
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108+
"2018-M02-29 to 2019-M02-29 is 1 year"
109+
);
110+
TemporalHelpers.assertDuration(
111+
start2.since(end, { largestUnit: "months" }),
112+
0, -11, 0, -29, 0, 0, 0, 0, 0, 0,
113+
"2018-M02-30 to 2019-M02-29 is 11 months 29 days, not 12 months"
114+
);
115+
TemporalHelpers.assertDuration(
116+
start2.since(end, { largestUnit: "years" }),
117+
0, -11, 0, -29, 0, 0, 0, 0, 0, 0,
118+
"2018-M02-30 to 2019-M02-29 is 11 months 29 days, not 1 year"
119+
);
120+
}
121+
122+
// Difference between end of 30-day leap month and end of the same leap month
123+
// with 29 days in a later year
124+
{
125+
const end = Temporal.PlainDate.from({ year: 2025, monthCode: "M06L", day: 29, calendar }, options);
126+
const start1 = Temporal.PlainDate.from({ year: 2017, monthCode: "M06L", day: 29, calendar }, options);
127+
const start2 = Temporal.PlainDate.from({ year: 2017, monthCode: "M06L", day: 30, calendar }, options);
128+
TemporalHelpers.assertDuration(
129+
start1.since(end, { largestUnit: "months" }),
130+
0, -99, 0, 0, 0, 0, 0, 0, 0, 0,
131+
"2017-M06L-29 to 2025-M06L-29 is 99 months"
132+
);
133+
TemporalHelpers.assertDuration(
134+
start1.since(end, { largestUnit: "years" }),
135+
-8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
136+
"2017-M06L-29 to 2025-M06L-29 is 8 years"
137+
);
138+
TemporalHelpers.assertDuration(
139+
start2.since(end, { largestUnit: "months" }),
140+
0, -98, 0, -29, 0, 0, 0, 0, 0, 0,
141+
"2017-M06L-30 to 2025-M06L-29 is 98 months 29 days, not 98 months"
142+
);
143+
TemporalHelpers.assertDuration(
144+
start2.since(end, { largestUnit: "years" }),
145+
-7, -12, 0, -29, 0, 0, 0, 0, 0, 0,
146+
"2017-M06L-30 to 2025-M06L-29 is 7 years 12 months 29 days, not 8 years"
147+
);
148+
}
149+
150+
// Case where both the month and day are not constrained
151+
{
152+
const end = Temporal.PlainDate.from({ year: 2018, monthCode: "M06", day: 29, calendar }, options);
153+
const start1 = Temporal.PlainDate.from({ year: 2017, monthCode: "M06L", day: 29, calendar }, options);
154+
const start2 = Temporal.PlainDate.from({ year: 2017, monthCode: "M06L", day: 30, calendar }, options);
155+
TemporalHelpers.assertDuration(
156+
start1.since(end, { largestUnit: "months" }),
157+
0, -12, 0, 0, 0, 0, 0, 0, 0, 0,
158+
"2017-M06L-29 to 2018-M06-29 is 12 months"
159+
);
160+
TemporalHelpers.assertDuration(
161+
start1.since(end, { largestUnit: "years" }),
162+
0, -12, 0, 0, 0, 0, 0, 0, 0, 0,
163+
"2017-M06L-29 to 2018-M06-29 is 12 months, not 1 year"
164+
);
165+
TemporalHelpers.assertDuration(
166+
start2.since(end, { largestUnit: "months" }),
167+
0, -11, 0, -29, 0, 0, 0, 0, 0, 0,
168+
"2017-M06L-30 to 2018-M06-29 is 11 months 29 days, not 12 months"
169+
);
170+
TemporalHelpers.assertDuration(
171+
start2.since(end, { largestUnit: "years" }),
172+
0, -11, 0, -29, 0, 0, 0, 0, 0, 0,
173+
"2017-M06L-30 to 2018-M06-29 is 11 months 29 days, not 1 year"
174+
);
175+
}

test/intl402/Temporal/PlainDate/prototype/since/wrapping-at-end-of-month-dangi.js

Lines changed: 100 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@ features: [Temporal, Intl.Era-monthcode]
99
---*/
1010

1111
const calendar = "dangi";
12+
const options = { overflow: "reject" };
1213

1314
// Difference between end of 30-day month to end of following 29-day month
1415
{
15-
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M06", day: 29, calendar });
16+
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M06", day: 29, calendar }, options);
1617
for (const largestUnit of ["years", "months"]) {
1718
TemporalHelpers.assertDuration(
18-
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 29, calendar }).since(end, { largestUnit }),
19+
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 29, calendar }, options).since(end, { largestUnit }),
1920
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
2021
`M05-29 (30d) to M06-29 (29d) is one month (${largestUnit})`
2122
);
2223
TemporalHelpers.assertDuration(
23-
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 30, calendar }).since(end, { largestUnit }),
24+
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 30, calendar }, options).since(end, { largestUnit }),
2425
0, 0, 0, -29, 0, 0, 0, 0, 0, 0,
2526
`M05-30 to M06-29 is 29 days, not one month (${largestUnit})`
2627
);
@@ -29,15 +30,15 @@ const calendar = "dangi";
2930

3031
// Difference between end of 30-day M04 to end of 29-day M04L
3132
{
32-
const end = Temporal.PlainDate.from({ year: 2020, monthCode: "M04L", day: 29, calendar });
33+
const end = Temporal.PlainDate.from({ year: 2020, monthCode: "M04L", day: 29, calendar }, options);
3334
for (const largestUnit of ["years", "months"]) {
3435
TemporalHelpers.assertDuration(
35-
Temporal.PlainDate.from({ year: 2020, monthCode: "M04", day: 29, calendar }).since(end, { largestUnit }),
36+
Temporal.PlainDate.from({ year: 2020, monthCode: "M04", day: 29, calendar }, options).since(end, { largestUnit }),
3637
0, -1, 0, 0, 0, 0, 0, 0, 0, 0,
3738
`M04-29 (30d) to M04L-29 (29d) is one month (${largestUnit})`
3839
);
3940
TemporalHelpers.assertDuration(
40-
Temporal.PlainDate.from({ year: 2020, monthCode: "M04", day: 30, calendar }).since(end, { largestUnit }),
41+
Temporal.PlainDate.from({ year: 2020, monthCode: "M04", day: 30, calendar }, options).since(end, { largestUnit }),
4142
0, 0, 0, -29, 0, 0, 0, 0, 0, 0,
4243
`M04-30 to M04L-29 (29d) is 29 days, not one month (${largestUnit})`
4344
);
@@ -47,15 +48,15 @@ const calendar = "dangi";
4748
// Difference between end of 30-day month to end of not-immediately-following
4849
// 29-day month
4950
{
50-
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M09", day: 29, calendar });
51+
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M09", day: 29, calendar }, options);
5152
for (const largestUnit of ["years", "months"]) {
5253
TemporalHelpers.assertDuration(
53-
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 29, calendar }).since(end, { largestUnit }),
54+
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 29, calendar }, options).since(end, { largestUnit }),
5455
0, -4, 0, 0, 0, 0, 0, 0, 0, 0,
5556
`M05-29 (30d) to M09-29 (29d) is 4 months (${largestUnit})`
5657
);
5758
TemporalHelpers.assertDuration(
58-
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 30, calendar }).since(end, { largestUnit }),
59+
Temporal.PlainDate.from({ year: 2023, monthCode: "M05", day: 30, calendar }, options).since(end, { largestUnit }),
5960
0, -3, 0, -29, 0, 0, 0, 0, 0, 0,
6061
`M05-30 to M09-29 (29d) is 3 months 29 days, not 4 months (${largestUnit})`
6162
);
@@ -65,25 +66,110 @@ const calendar = "dangi";
6566
// Difference between end of 30-day month in one year to 29-day month in later
6667
// year
6768
{
68-
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M09", day: 29, calendar });
69+
const end = Temporal.PlainDate.from({ year: 2023, monthCode: "M09", day: 29, calendar }, options);
70+
const start1 = Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 29, calendar }, options);
71+
const start2 = Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 30, calendar }, options);
6972
TemporalHelpers.assertDuration(
70-
Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 29, calendar }).since(end, { largestUnit: "months" }),
73+
start1.since(end, { largestUnit: "months" }),
7174
0, -29, 0, 0, 0, 0, 0, 0, 0, 0,
7275
"2021-M05-29 (30d) to 2023-M09-29 (29d) is 29 days"
7376
);
7477
TemporalHelpers.assertDuration(
75-
Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 29, calendar }).since(end, { largestUnit: "years" }),
78+
start1.since(end, { largestUnit: "years" }),
7679
-2, -4, 0, 0, 0, 0, 0, 0, 0, 0,
7780
"2021-M05-29 (30d) to 2023-M09-29 (29d) is 2 years, 4 months"
7881
);
7982
TemporalHelpers.assertDuration(
80-
Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 30, calendar }).since(end, { largestUnit: "months" }),
83+
start2.since(end, { largestUnit: "months" }),
8184
0, -28, 0, -29, 0, 0, 0, 0, 0, 0,
8285
"2021-M05-30 to 2023-M09-29 (29d) is 28 months, 29 days, not 29 months"
8386
);
8487
TemporalHelpers.assertDuration(
85-
Temporal.PlainDate.from({ year: 2021, monthCode: "M05", day: 30, calendar }).since(end, { largestUnit: "years" }),
88+
start2.since(end, { largestUnit: "years" }),
8689
-2, -3, 0, -29, 0, 0, 0, 0, 0, 0,
8790
"2021-M05-30 to 2023-M09-29 (29d) is 2 years, 3 months, 29 days, not 2 years 4 months"
8891
);
8992
}
93+
94+
// Difference between end of 30-day common month and end of the same month with
95+
// 29 days in a later year
96+
{
97+
const end = Temporal.PlainDate.from({ year: 2019, monthCode: "M02", day: 29, calendar }, options);
98+
const start1 = Temporal.PlainDate.from({ year: 2018, monthCode: "M02", day: 29, calendar }, options);
99+
const start2 = Temporal.PlainDate.from({ year: 2018, monthCode: "M02", day: 30, calendar }, options);
100+
TemporalHelpers.assertDuration(
101+
start1.since(end, { largestUnit: "months" }),
102+
0, -12, 0, 0, 0, 0, 0, 0, 0, 0,
103+
"2018-M02-29 to 2019-M02-29 is 12 months"
104+
);
105+
TemporalHelpers.assertDuration(
106+
start1.since(end, { largestUnit: "years" }),
107+
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108+
"2018-M02-29 to 2019-M02-29 is 1 year"
109+
);
110+
TemporalHelpers.assertDuration(
111+
start2.since(end, { largestUnit: "months" }),
112+
0, -11, 0, -29, 0, 0, 0, 0, 0, 0,
113+
"2018-M02-30 to 2019-M02-29 is 11 months 29 days, not 12 months"
114+
);
115+
TemporalHelpers.assertDuration(
116+
start2.since(end, { largestUnit: "years" }),
117+
0, -11, 0, -29, 0, 0, 0, 0, 0, 0,
118+
"2018-M02-30 to 2019-M02-29 is 11 months 29 days, not 1 year"
119+
);
120+
}
121+
122+
// Difference between end of 30-day leap month and end of the same leap month
123+
// with 29 days in a later year
124+
{
125+
const end = Temporal.PlainDate.from({ year: 1987, monthCode: "M06L", day: 29, calendar }, options);
126+
const start1 = Temporal.PlainDate.from({ year: 1979, monthCode: "M06L", day: 29, calendar }, options);
127+
const start2 = Temporal.PlainDate.from({ year: 1979, monthCode: "M06L", day: 30, calendar }, options);
128+
TemporalHelpers.assertDuration(
129+
start1.since(end, { largestUnit: "months" }),
130+
0, -99, 0, 0, 0, 0, 0, 0, 0, 0,
131+
"1979-M06L-29 to 1987-M06L-29 is 99 months"
132+
);
133+
TemporalHelpers.assertDuration(
134+
start1.since(end, { largestUnit: "years" }),
135+
-8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
136+
"1979-M06L-29 to 1987-M06L-29 is 8 years"
137+
);
138+
TemporalHelpers.assertDuration(
139+
start2.since(end, { largestUnit: "months" }),
140+
0, -98, 0, -29, 0, 0, 0, 0, 0, 0,
141+
"1979-M06L-30 to 1987-M06L-29 is 98 months 29 days, not 98 months"
142+
);
143+
TemporalHelpers.assertDuration(
144+
start2.since(end, { largestUnit: "years" }),
145+
-7, -12, 0, -29, 0, 0, 0, 0, 0, 0,
146+
"1979-M06L-30 to 1987-M06L-29 is 7 years 12 months 29 days, not 8 years"
147+
);
148+
}
149+
150+
// Case where both the month and day are not constrained
151+
{
152+
const end = Temporal.PlainDate.from({ year: 1956, monthCode: "M03", day: 29, calendar }, options);
153+
const start1 = Temporal.PlainDate.from({ year: 1955, monthCode: "M03L", day: 29, calendar }, options);
154+
const start2 = Temporal.PlainDate.from({ year: 1955, monthCode: "M03L", day: 30, calendar }, options);
155+
TemporalHelpers.assertDuration(
156+
start1.since(end, { largestUnit: "months" }),
157+
0, -12, 0, 0, 0, 0, 0, 0, 0, 0,
158+
"1955-M03L-29 to 1956-M03-29 is 12 months"
159+
);
160+
TemporalHelpers.assertDuration(
161+
start1.since(end, { largestUnit: "years" }),
162+
0, -12, 0, 0, 0, 0, 0, 0, 0, 0,
163+
"1955-M03L-29 to 1956-M03-29 is 12 months, not 1 year"
164+
);
165+
TemporalHelpers.assertDuration(
166+
start2.since(end, { largestUnit: "months" }),
167+
0, -11, 0, -29, 0, 0, 0, 0, 0, 0,
168+
"1955-M03L-30 to 1956-M03-29 is 11 months 29 days, not 12 months"
169+
);
170+
TemporalHelpers.assertDuration(
171+
start2.since(end, { largestUnit: "years" }),
172+
0, -11, 0, -29, 0, 0, 0, 0, 0, 0,
173+
"1955-M03L-30 to 1956-M03-29 is 11 months 29 days, not 1 year"
174+
);
175+
}

0 commit comments

Comments
 (0)