-
Notifications
You must be signed in to change notification settings - Fork 223
Compute LunarChinese reference years with new algorithm #7007
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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, | ||
|
@@ -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, | ||
Comment on lines
-216
to
+215
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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, | ||
|
@@ -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, | ||
|
@@ -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, | ||
robertbastian marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(3, true, false) => 1966, | ||
(3, true, true) => 1955, | ||
(4, false, false) => 1972, | ||
|
@@ -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, | ||
robertbastian marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(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)) | ||
|
@@ -2299,4 +2283,77 @@ mod test { | |
); | ||
} | ||
} | ||
|
||
#[test] | ||
#[ignore] | ||
fn generate_reference_years() { | ||
use crate::Date; | ||
let calendar = crate::cal::LunarChinese::new_china(); | ||
robertbastian marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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!(),") | ||
} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
confirmed: https://www.hko.gov.hk/en/gts/time/calendar/pdf/files/2014e.pdf
There was a problem hiding this comment.
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.