Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 83 additions & 26 deletions components/calendar/src/cal/chinese.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,7 @@ impl Rules for China {
let Some((number, is_leap)) = month_code.parsed() else {
return Err(DateError::UnknownMonthCode(month_code));
};
// Computed via code from
// <https://github.com/unicode-org/icu4x/pull/6910#issuecomment-3303786919>
// Computed by `generate_reference_years`
let extended = match (number, is_leap, day > 29) {
(1, false, false) => 1972,
(1, false, true) => 1970,
Expand Down Expand Up @@ -213,21 +212,17 @@ impl Rules for China {
(8, true, true) => 1718,
(9, false, false) => 1972,
(9, false, true) => 1972,
(9, true, false) => 1832,
(9, true, false) => 2014,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in these cases because they were not super far in the past I continued with the backwards-looking algorithm, but the 1900 cutoff seems good.

Comment on lines -216 to +215
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Observation: I see a M09L (闰九月) in the year 2014 in the PMO file and it has 29 days

(9, true, true) => -5738,
(10, false, false) => 1972,
(10, false, true) => 1972,
(10, true, false) => 1870,
(10, true, false) => 1984,
Comment on lines -220 to +219
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Observation: I do indeed see a M10L (闰十月) in the year 1984 in the PMO file and it has 29 days

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(10, true, true) => -4098,
// Dec 31, 1972 is 1972-M11-26, dates after that
// are in the next year
(11, false, false) if day > 26 => 1971,
(11, false, false) => 1972,
(11, false, true) => 1969,
// Specced backwards-looking algorithm produces 1642, but
// 2033 is a better date with a forwards-looking algorithm.
// See <https://github.com/tc39/proposal-intl-era-monthcode/issues/60#issuecomment-3192982095>
// Data from: <https://github.com/unicode-org/icu4x/pull/6910#issuecomment-3303988559>
(11, true, false) => 2033,
(11, true, true) => -2173,
(12, false, false) => 1971,
Expand Down Expand Up @@ -342,13 +337,7 @@ impl Rules for Dangi {
let Some((number, is_leap)) = month_code.parsed() else {
return Err(DateError::UnknownMonthCode(month_code));
};
// Computed via code from
// <https://github.com/unicode-org/icu4x/pull/6910#issuecomment-3303786919>
//
// Some (marked) dates use a forward looking algorithm from
// <https://github.com/tc39/proposal-intl-era-monthcode/issues/60#issuecomment-3192982095>
// to produce a better in-range date.
// Code for that is <https://github.com/unicode-org/icu4x/pull/6910#issuecomment-3303988559>
// Computed by `generate_reference_years`
let extended = match (number, is_leap, day > 29) {
(1, false, false) => 1972,
(1, false, true) => 1970,
Expand All @@ -359,7 +348,7 @@ impl Rules for Dangi {
(2, true, false) => 1947,
(2, true, true) => 1765,
(3, false, false) => 1972,
(3, false, true) => 1968,
(3, false, true) => 1966,
(3, true, false) => 1966,
(3, true, true) => 1955,
(4, false, false) => 1972,
Expand All @@ -381,31 +370,26 @@ impl Rules for Dangi {
(8, false, false) => 1972,
(8, false, true) => 1971,
(8, true, false) => 1957,
// Uses forward-looking algorithm (was: 1718)
(8, true, true) => 2052,
(8, true, true) => 1718,
(9, false, false) => 1972,
(9, false, true) => 1972,
// Uses forward-looking algorithm (was: 1832)
(9, true, false) => 1972,
(9, true, false) => 2014,
(9, true, true) => -5738,
(10, false, false) => 1972,
(10, false, true) => 1972,
// Uses forward-looking algorithm (was: 1870)
(10, true, false) => 1984,
(10, true, true) => -3946,
(10, true, true) => -4098,
// Dec 31, 1972 is 1972-M11-26, dates after that
// are in the next year
(11, false, false) if day > 26 => 1971,
(11, false, false) => 1972,
(11, false, true) => 1969,
// Uses forward-looking algorithm (was: 1851)
(11, true, false) => 2033,
(11, true, true) => -2173,
(12, false, false) => 1971,
(12, false, true) => 1971,
(12, true, false) => 1889,
(12, true, true) => -1182,

(12, true, false) => 1403,
(12, true, true) => -180,
_ => return Err(DateError::UnknownMonthCode(month_code)),
};
Ok(self.year_data(extended))
Expand Down Expand Up @@ -2299,4 +2283,77 @@ mod test {
);
}
}

#[test]
#[ignore]
fn generate_reference_years() {
use crate::Date;
let calendar = crate::cal::LunarChinese::new_china();
let reference_year_end = Date::from_rata_die(
crate::cal::abstract_gregorian::LAST_DAY_OF_REFERENCE_YEAR,
calendar,
);
let year_1900_start = Date::try_new_gregorian(1900, 1, 1)
.unwrap()
.to_calendar(calendar);
let year_2035_end = Date::try_new_gregorian(2035, 12, 31)
.unwrap()
.to_calendar(calendar);
for month in 1..=12 {
for leap in [false, true] {
'outer: for long in [false, true] {
for (start_year, start_month, end_year, end_month, by) in [
(
reference_year_end.extended_year(),
reference_year_end.month().month_number(),
year_1900_start.extended_year(),
year_1900_start.month().month_number(),
-1,
),
(
reference_year_end.extended_year(),
reference_year_end.month().month_number(),
year_2035_end.extended_year(),
year_2035_end.month().month_number(),
1,
),
(
year_1900_start.extended_year(),
year_1900_start.month().month_number(),
-10000,
1,
-1,
),
] {
let mut year = start_year;
while year * by < end_year * by {
if year == start_year && month as i32 * by < start_month as i32 * by
|| year == end_year && month as i32 * by > end_month as i32 * by
{
year += by;
continue;
}
let data = China.year_data(year);
let leap_month = data.leap_month().unwrap_or(15);
let days_in_month = data.days_in_month({
if leap && month + 1 == leap_month {
month + 1
} else {
month + (month + 1 > leap_month) as u8
}
});
if (!long || (days_in_month == 30))
&& (!leap || month + 1 == leap_month)
{
println!("({month}, {leap:?}, {long:?}) => {year},");
continue 'outer;
}
year += by;
}
}
println!("({month}, {leap:?}, {long:?}) => todo!(),")
}
}
}
}
}