Skip to content

Commit 66aba40

Browse files
Compute LunarChinese reference years with new algorithm (#7007)
1 parent 1b2f61a commit 66aba40

File tree

1 file changed

+83
-26
lines changed

1 file changed

+83
-26
lines changed

components/calendar/src/cal/chinese.rs

Lines changed: 83 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,7 @@ impl Rules for China {
176176
let Some((number, is_leap)) = month_code.parsed() else {
177177
return Err(DateError::UnknownMonthCode(month_code));
178178
};
179-
// Computed via code from
180-
// <https://github.com/unicode-org/icu4x/pull/6910#issuecomment-3303786919>
179+
// Computed by `generate_reference_years`
181180
let extended = match (number, is_leap, day > 29) {
182181
(1, false, false) => 1972,
183182
(1, false, true) => 1970,
@@ -213,21 +212,17 @@ impl Rules for China {
213212
(8, true, true) => 1718,
214213
(9, false, false) => 1972,
215214
(9, false, true) => 1972,
216-
(9, true, false) => 1832,
215+
(9, true, false) => 2014,
217216
(9, true, true) => -5738,
218217
(10, false, false) => 1972,
219218
(10, false, true) => 1972,
220-
(10, true, false) => 1870,
219+
(10, true, false) => 1984,
221220
(10, true, true) => -4098,
222221
// Dec 31, 1972 is 1972-M11-26, dates after that
223222
// are in the next year
224223
(11, false, false) if day > 26 => 1971,
225224
(11, false, false) => 1972,
226225
(11, false, true) => 1969,
227-
// Specced backwards-looking algorithm produces 1642, but
228-
// 2033 is a better date with a forwards-looking algorithm.
229-
// See <https://github.com/tc39/proposal-intl-era-monthcode/issues/60#issuecomment-3192982095>
230-
// Data from: <https://github.com/unicode-org/icu4x/pull/6910#issuecomment-3303988559>
231226
(11, true, false) => 2033,
232227
(11, true, true) => -2173,
233228
(12, false, false) => 1971,
@@ -342,13 +337,7 @@ impl Rules for Dangi {
342337
let Some((number, is_leap)) = month_code.parsed() else {
343338
return Err(DateError::UnknownMonthCode(month_code));
344339
};
345-
// Computed via code from
346-
// <https://github.com/unicode-org/icu4x/pull/6910#issuecomment-3303786919>
347-
//
348-
// Some (marked) dates use a forward looking algorithm from
349-
// <https://github.com/tc39/proposal-intl-era-monthcode/issues/60#issuecomment-3192982095>
350-
// to produce a better in-range date.
351-
// Code for that is <https://github.com/unicode-org/icu4x/pull/6910#issuecomment-3303988559>
340+
// Computed by `generate_reference_years`
352341
let extended = match (number, is_leap, day > 29) {
353342
(1, false, false) => 1972,
354343
(1, false, true) => 1970,
@@ -359,7 +348,7 @@ impl Rules for Dangi {
359348
(2, true, false) => 1947,
360349
(2, true, true) => 1765,
361350
(3, false, false) => 1972,
362-
(3, false, true) => 1968,
351+
(3, false, true) => 1966,
363352
(3, true, false) => 1966,
364353
(3, true, true) => 1955,
365354
(4, false, false) => 1972,
@@ -381,31 +370,26 @@ impl Rules for Dangi {
381370
(8, false, false) => 1972,
382371
(8, false, true) => 1971,
383372
(8, true, false) => 1957,
384-
// Uses forward-looking algorithm (was: 1718)
385-
(8, true, true) => 2052,
373+
(8, true, true) => 1718,
386374
(9, false, false) => 1972,
387375
(9, false, true) => 1972,
388-
// Uses forward-looking algorithm (was: 1832)
389-
(9, true, false) => 1972,
376+
(9, true, false) => 2014,
390377
(9, true, true) => -5738,
391378
(10, false, false) => 1972,
392379
(10, false, true) => 1972,
393-
// Uses forward-looking algorithm (was: 1870)
394380
(10, true, false) => 1984,
395-
(10, true, true) => -3946,
381+
(10, true, true) => -4098,
396382
// Dec 31, 1972 is 1972-M11-26, dates after that
397383
// are in the next year
398384
(11, false, false) if day > 26 => 1971,
399385
(11, false, false) => 1972,
400386
(11, false, true) => 1969,
401-
// Uses forward-looking algorithm (was: 1851)
402387
(11, true, false) => 2033,
403388
(11, true, true) => -2173,
404389
(12, false, false) => 1971,
405390
(12, false, true) => 1971,
406-
(12, true, false) => 1889,
407-
(12, true, true) => -1182,
408-
391+
(12, true, false) => 1403,
392+
(12, true, true) => -180,
409393
_ => return Err(DateError::UnknownMonthCode(month_code)),
410394
};
411395
Ok(self.year_data(extended))
@@ -2299,4 +2283,77 @@ mod test {
22992283
);
23002284
}
23012285
}
2286+
2287+
#[test]
2288+
#[ignore]
2289+
fn generate_reference_years() {
2290+
use crate::Date;
2291+
let calendar = crate::cal::LunarChinese::new_china();
2292+
let reference_year_end = Date::from_rata_die(
2293+
crate::cal::abstract_gregorian::LAST_DAY_OF_REFERENCE_YEAR,
2294+
calendar,
2295+
);
2296+
let year_1900_start = Date::try_new_gregorian(1900, 1, 1)
2297+
.unwrap()
2298+
.to_calendar(calendar);
2299+
let year_2035_end = Date::try_new_gregorian(2035, 12, 31)
2300+
.unwrap()
2301+
.to_calendar(calendar);
2302+
for month in 1..=12 {
2303+
for leap in [false, true] {
2304+
'outer: for long in [false, true] {
2305+
for (start_year, start_month, end_year, end_month, by) in [
2306+
(
2307+
reference_year_end.extended_year(),
2308+
reference_year_end.month().month_number(),
2309+
year_1900_start.extended_year(),
2310+
year_1900_start.month().month_number(),
2311+
-1,
2312+
),
2313+
(
2314+
reference_year_end.extended_year(),
2315+
reference_year_end.month().month_number(),
2316+
year_2035_end.extended_year(),
2317+
year_2035_end.month().month_number(),
2318+
1,
2319+
),
2320+
(
2321+
year_1900_start.extended_year(),
2322+
year_1900_start.month().month_number(),
2323+
-10000,
2324+
1,
2325+
-1,
2326+
),
2327+
] {
2328+
let mut year = start_year;
2329+
while year * by < end_year * by {
2330+
if year == start_year && month as i32 * by < start_month as i32 * by
2331+
|| year == end_year && month as i32 * by > end_month as i32 * by
2332+
{
2333+
year += by;
2334+
continue;
2335+
}
2336+
let data = China.year_data(year);
2337+
let leap_month = data.leap_month().unwrap_or(15);
2338+
let days_in_month = data.days_in_month({
2339+
if leap && month + 1 == leap_month {
2340+
month + 1
2341+
} else {
2342+
month + (month + 1 > leap_month) as u8
2343+
}
2344+
});
2345+
if (!long || (days_in_month == 30))
2346+
&& (!leap || month + 1 == leap_month)
2347+
{
2348+
println!("({month}, {leap:?}, {long:?}) => {year},");
2349+
continue 'outer;
2350+
}
2351+
year += by;
2352+
}
2353+
}
2354+
println!("({month}, {leap:?}, {long:?}) => todo!(),")
2355+
}
2356+
}
2357+
}
2358+
}
23022359
}

0 commit comments

Comments
 (0)