Skip to content

Commit

Permalink
Use packed data within ChineseBasedYearInfo (#4465)
Browse files Browse the repository at this point in the history
Part of #3933

This does not yet add data loading, but it gets very close to it.

This PR makes the size of Date not bloat too much, without requiring
much computation for any of the getters -- they're all basic bit
operations.
  • Loading branch information
Manishearth authored Dec 18, 2023
1 parent 825041b commit 7a27226
Show file tree
Hide file tree
Showing 4 changed files with 360 additions and 263 deletions.
70 changes: 6 additions & 64 deletions components/calendar/src/chinese.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,64 +228,7 @@ impl Calendar for Chinese {
/// leap months. For example, in a year where an intercalary month is added after the second
/// month, the month codes for ordinal months 1, 2, 3, 4, 5 would be "M01", "M02", "M02L", "M03", "M04".
fn month(&self, date: &Self::DateInner) -> types::FormattableMonth {
let ordinal = date.0 .0.month;
let leap_month_option = date.0 .0.year_info.leap_month;
let leap_month = if let Some(leap) = leap_month_option {
leap.get()
} else {
14
};
let code_inner = if leap_month == ordinal {
// Month cannot be 1 because a year cannot have a leap month before the first actual month,
// and the maximum num of months ina leap year is 13.
debug_assert!((2..=13).contains(&ordinal));
match ordinal {
2 => tinystr!(4, "M01L"),
3 => tinystr!(4, "M02L"),
4 => tinystr!(4, "M03L"),
5 => tinystr!(4, "M04L"),
6 => tinystr!(4, "M05L"),
7 => tinystr!(4, "M06L"),
8 => tinystr!(4, "M07L"),
9 => tinystr!(4, "M08L"),
10 => tinystr!(4, "M09L"),
11 => tinystr!(4, "M10L"),
12 => tinystr!(4, "M11L"),
13 => tinystr!(4, "M12L"),
_ => tinystr!(4, "und"),
}
} else {
let mut adjusted_ordinal = ordinal;
if ordinal > leap_month {
// Before adjusting for leap month, if ordinal > leap_month,
// the month cannot be 1 because this implies the leap month is < 1, which is impossible;
// cannot be 2 because that implies the leap month is = 1, which is impossible,
// and cannot be more than 13 because max number of months in a year is 13.
debug_assert!((2..=13).contains(&ordinal));
adjusted_ordinal -= 1;
}
debug_assert!((1..=12).contains(&adjusted_ordinal));
match adjusted_ordinal {
1 => tinystr!(4, "M01"),
2 => tinystr!(4, "M02"),
3 => tinystr!(4, "M03"),
4 => tinystr!(4, "M04"),
5 => tinystr!(4, "M05"),
6 => tinystr!(4, "M06"),
7 => tinystr!(4, "M07"),
8 => tinystr!(4, "M08"),
9 => tinystr!(4, "M09"),
10 => tinystr!(4, "M10"),
11 => tinystr!(4, "M11"),
12 => tinystr!(4, "M12"),
_ => tinystr!(4, "und"),
}
};
let code = types::MonthCode(code_inner);
types::FormattableMonth {
ordinal: ordinal as u32,
code,
}
date.0.month()
}

/// The calendar-specific day-of-month represented by `date`
Expand All @@ -297,13 +240,11 @@ impl Calendar for Chinese {
fn day_of_year_info(&self, date: &Self::DateInner) -> types::DayOfYearInfo {
let prev_year = date.0 .0.year.saturating_sub(1);
let next_year = date.0 .0.year.saturating_add(1);
// TODO(#3933): we should maybe have this cached already
let prev_info = self.get_precomputed_data().load_or_compute_info(prev_year);
types::DayOfYearInfo {
day_of_year: date.0.day_of_year(),
days_in_year: date.0.days_in_year_inner(),
prev_year: Self::format_chinese_year(prev_year, None),
days_in_prev_year: Self::days_in_provided_year(prev_year, prev_info),
days_in_prev_year: date.0.days_in_prev_year(),
next_year: Self::format_chinese_year(next_year, None),
}
}
Expand Down Expand Up @@ -402,8 +343,9 @@ impl<A: AsCalendar<Calendar = Chinese>> DateTime<A> {
}
}

type ChineseCB = calendrical_calculations::chinese_based::Chinese;
impl ChineseBasedWithDataLoading for Chinese {
type CB = calendrical_calculations::chinese_based::Chinese;
type CB = ChineseCB;
fn get_precomputed_data(&self) -> ChineseBasedPrecomputedData<Self::CB> {
Default::default()
}
Expand All @@ -426,7 +368,7 @@ impl Chinese {
let cyclic = (number - 1).rem_euclid(60) as u8;
let cyclic = NonZeroU8::new(cyclic + 1); // 1-indexed
let rata_die_in_year = if let Some(info) = year_info_option {
info.new_year
info.new_year::<ChineseCB>(year)
} else {
Inner::fixed_mid_year_from_year(number)
};
Expand Down Expand Up @@ -692,7 +634,7 @@ mod test {
let iso = Date::try_new_iso_date(year, 6, 1).unwrap();
let chinese_date = iso.to_calendar(Chinese);
assert!(chinese_date.is_in_leap_year());
let new_year = chinese_date.inner.0 .0.year_info.new_year;
let new_year = chinese_date.inner.0.new_year();
assert_eq!(
expected_month,
calendrical_calculations::chinese_based::get_leap_month_from_new_year::<
Expand Down
Loading

0 comments on commit 7a27226

Please sign in to comment.