Skip to content
Merged
Show file tree
Hide file tree
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
5 changes: 3 additions & 2 deletions components/calendar/src/cal/abstract_gregorian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ pub(crate) trait GregorianYears: Clone + core::fmt::Debug {
// Positive if after 0 CE
const EXTENDED_YEAR_OFFSET: i32 = 0;

fn extended_from_era_year(&self, era: Option<&str>, year: i32) -> Result<i32, UnknownEraError>;
fn extended_from_era_year(&self, era: Option<&[u8]>, year: i32)
-> Result<i32, UnknownEraError>;

fn era_year_from_extended(&self, extended_year: i32, month: u8, day: u8) -> EraYear;

Expand Down Expand Up @@ -90,7 +91,7 @@ impl<Y: GregorianYears> DateFieldsResolver for AbstractGregorian<Y> {
#[inline]
fn year_info_from_era(
&self,
era: &str,
era: &[u8],
era_year: i32,
) -> Result<Self::YearInfo, UnknownEraError> {
Ok(self.0.extended_from_era_year(Some(era), era_year)? + Y::EXTENDED_YEAR_OFFSET)
Expand Down
8 changes: 6 additions & 2 deletions components/calendar/src/cal/buddhist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,13 @@ pub(crate) struct BuddhistEra;
impl GregorianYears for BuddhistEra {
const EXTENDED_YEAR_OFFSET: i32 = -543;

fn extended_from_era_year(&self, era: Option<&str>, year: i32) -> Result<i32, UnknownEraError> {
fn extended_from_era_year(
&self,
era: Option<&[u8]>,
year: i32,
) -> Result<i32, UnknownEraError> {
match era {
Some("be") | None => Ok(year),
Some(b"be") | None => Ok(year),
_ => Err(UnknownEraError),
}
}
Expand Down
2 changes: 1 addition & 1 deletion components/calendar/src/cal/chinese.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ impl<R: Rules> DateFieldsResolver for LunarChinese<R> {
#[inline]
fn year_info_from_era(
&self,
_era: &str,
_era: &[u8],
_era_year: i32,
) -> Result<Self::YearInfo, UnknownEraError> {
// This calendar has no era codes
Expand Down
4 changes: 2 additions & 2 deletions components/calendar/src/cal/coptic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ impl DateFieldsResolver for Coptic {
#[inline]
fn year_info_from_era(
&self,
era: &str,
era: &[u8],
era_year: i32,
) -> Result<Self::YearInfo, UnknownEraError> {
match era {
"am" => Ok(era_year),
b"am" => Ok(era_year),
_ => Err(UnknownEraError),
}
}
Expand Down
6 changes: 3 additions & 3 deletions components/calendar/src/cal/ethiopian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ impl DateFieldsResolver for Ethiopian {
#[inline]
fn year_info_from_era(
&self,
era: &str,
era: &[u8],
era_year: i32,
) -> Result<Self::YearInfo, UnknownEraError> {
match (self.era_style(), era) {
(EthiopianEraStyle::AmeteMihret, "am") => Ok(era_year + AMETE_MIHRET_OFFSET),
(_, "aa") => Ok(era_year + AMETE_ALEM_OFFSET),
(EthiopianEraStyle::AmeteMihret, b"am") => Ok(era_year + AMETE_MIHRET_OFFSET),
(_, b"aa") => Ok(era_year + AMETE_ALEM_OFFSET),
(_, _) => Err(UnknownEraError),
}
}
Expand Down
10 changes: 7 additions & 3 deletions components/calendar/src/cal/gregorian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ impl_with_abstract_gregorian!(crate::cal::Gregorian, GregorianDateInner, CeBce,
pub(crate) struct CeBce;

impl GregorianYears for CeBce {
fn extended_from_era_year(&self, era: Option<&str>, year: i32) -> Result<i32, UnknownEraError> {
fn extended_from_era_year(
&self,
era: Option<&[u8]>,
year: i32,
) -> Result<i32, UnknownEraError> {
match era {
None => Ok(year),
Some("ad" | "ce") => Ok(year),
Some("bce" | "bc") => Ok(1 - year),
Some(b"ad" | b"ce") => Ok(year),
Some(b"bce" | b"bc") => Ok(1 - year),
Some(_) => Err(UnknownEraError),
}
}
Expand Down
4 changes: 2 additions & 2 deletions components/calendar/src/cal/hebrew.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,11 @@ impl DateFieldsResolver for Hebrew {
#[inline]
fn year_info_from_era(
&self,
era: &str,
era: &[u8],
era_year: i32,
) -> Result<Self::YearInfo, UnknownEraError> {
match era {
"am" => Ok(HebrewYearInfo::compute(era_year)),
b"am" => Ok(HebrewYearInfo::compute(era_year)),
_ => Err(UnknownEraError),
}
}
Expand Down
6 changes: 3 additions & 3 deletions components/calendar/src/cal/hijri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -725,12 +725,12 @@ impl<R: Rules> DateFieldsResolver for Hijri<R> {
#[inline]
fn year_info_from_era(
&self,
era: &str,
era: &[u8],
era_year: i32,
) -> Result<Self::YearInfo, UnknownEraError> {
let extended_year = match era {
"ah" => era_year,
"bh" => 1 - era_year,
b"ah" => era_year,
b"bh" => 1 - era_year,
_ => return Err(UnknownEraError),
};
Ok(self.year_info_from_extended(extended_year))
Expand Down
4 changes: 2 additions & 2 deletions components/calendar/src/cal/indian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@ impl DateFieldsResolver for Indian {
#[inline]
fn year_info_from_era(
&self,
era: &str,
era: &[u8],
era_year: i32,
) -> Result<Self::YearInfo, UnknownEraError> {
match era {
"shaka" => Ok(era_year),
b"shaka" => Ok(era_year),
_ => Err(UnknownEraError),
}
}
Expand Down
8 changes: 6 additions & 2 deletions components/calendar/src/cal/iso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ impl_with_abstract_gregorian!(crate::cal::Iso, IsoDateInner, IsoEra, _x, IsoEra)
pub(crate) struct IsoEra;

impl GregorianYears for IsoEra {
fn extended_from_era_year(&self, era: Option<&str>, year: i32) -> Result<i32, UnknownEraError> {
fn extended_from_era_year(
&self,
era: Option<&[u8]>,
year: i32,
) -> Result<i32, UnknownEraError> {
match era {
Some("default") | None => Ok(year),
Some(b"default") | None => Ok(year),
Some(_) => Err(UnknownEraError),
}
}
Expand Down
32 changes: 20 additions & 12 deletions components/calendar/src/cal/japanese.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,11 @@ const REIWA_START: EraStartDate = EraStartDate {
};

impl GregorianYears for &'_ Japanese {
fn extended_from_era_year(&self, era: Option<&str>, year: i32) -> Result<i32, UnknownEraError> {
fn extended_from_era_year(
&self,
era: Option<&[u8]>,
year: i32,
) -> Result<i32, UnknownEraError> {
if let Ok(g) = CeBce.extended_from_era_year(era, year) {
return Ok(g);
}
Expand All @@ -179,28 +183,32 @@ impl GregorianYears for &'_ Japanese {
};

// Avoid linear search by trying well known eras
if era == "reiwa" {
if era == b"reiwa" {
return Ok(year - 1 + REIWA_START.year);
} else if era == "heisei" {
} else if era == b"heisei" {
return Ok(year - 1 + HEISEI_START.year);
} else if era == "showa" {
} else if era == b"showa" {
return Ok(year - 1 + SHOWA_START.year);
} else if era == "taisho" {
} else if era == b"taisho" {
return Ok(year - 1 + TAISHO_START.year);
} else if era == "meiji" {
} else if era == b"meiji" {
return Ok(year - 1 + MEIJI_START.year);
}

let data = &self.eras.get().dates_to_eras;

// Try to avoid linear search by binary searching for the year suffix
if let Some(start_year) = era.split('-').nth(1).and_then(|y| y.parse::<i32>().ok()) {
if let Some(start_year) = era
.split(|x| *x == b'-')
.nth(1)
.and_then(|y| core::str::from_utf8(y).ok()?.parse::<i32>().ok())
{
if let Ok(index) = data.binary_search_by(|(d, _)| d.year.cmp(&start_year)) {
// There is a slight chance we hit the case where there are two eras in the same year
// There are a couple of rare cases of this, but it's not worth writing a range-based binary search
// to catch them since this is an optimization
#[expect(clippy::unwrap_used)] // binary search
if data.get(index).unwrap().1 == era {
if data.get(index).unwrap().1.as_bytes() == era {
return Ok(start_year + year - 1);
}
}
Expand All @@ -210,7 +218,7 @@ impl GregorianYears for &'_ Japanese {
let era_start = data
.iter()
.rev()
.find_map(|(s, e)| (e == era).then_some(s))
.find_map(|(s, e)| (e.as_bytes() == era).then_some(s))
.ok_or(UnknownEraError)?;
Ok(era_start.year + year - 1)
}
Expand Down Expand Up @@ -341,7 +349,7 @@ impl Date<Japanese> {
) -> Result<Date<A>, DateError> {
let extended = japanese_calendar
.as_calendar()
.extended_from_era_year(Some(era), year)?;
.extended_from_era_year(Some(era.as_bytes()), year)?;
Ok(Date::from_raw(
JapaneseDateInner(ArithmeticDate::new_gregorian::<&Japanese>(
extended, month, day,
Expand Down Expand Up @@ -392,8 +400,8 @@ impl Date<JapaneseExtended> {
day: u8,
japanext_calendar: A,
) -> Result<Date<A>, DateError> {
let extended =
(&japanext_calendar.as_calendar().0).extended_from_era_year(Some(era), year)?;
let extended = (&japanext_calendar.as_calendar().0)
.extended_from_era_year(Some(era.as_bytes()), year)?;
Ok(Date::from_raw(
JapaneseExtendedDateInner(ArithmeticDate::new_gregorian::<&Japanese>(
extended, month, day,
Expand Down
6 changes: 3 additions & 3 deletions components/calendar/src/cal/julian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ impl DateFieldsResolver for Julian {
#[inline]
fn year_info_from_era(
&self,
era: &str,
era: &[u8],
era_year: i32,
) -> Result<Self::YearInfo, UnknownEraError> {
match era {
"ad" | "ce" => Ok(era_year),
"bc" | "bce" => Ok(1 - era_year),
b"ad" | b"ce" => Ok(era_year),
b"bc" | b"bce" => Ok(1 - era_year),
_ => Err(UnknownEraError),
}
}
Expand Down
4 changes: 2 additions & 2 deletions components/calendar/src/cal/persian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ impl DateFieldsResolver for Persian {
#[inline]
fn year_info_from_era(
&self,
era: &str,
era: &[u8],
era_year: i32,
) -> Result<Self::YearInfo, UnknownEraError> {
match era {
"ap" | "sh" | "hs" => Ok(era_year),
b"ap" | b"sh" | b"hs" => Ok(era_year),
_ => Err(UnknownEraError),
}
}
Expand Down
10 changes: 7 additions & 3 deletions components/calendar/src/cal/roc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,15 @@ pub(crate) struct RocEra;
impl GregorianYears for RocEra {
const EXTENDED_YEAR_OFFSET: i32 = 1911;

fn extended_from_era_year(&self, era: Option<&str>, year: i32) -> Result<i32, UnknownEraError> {
fn extended_from_era_year(
&self,
era: Option<&[u8]>,
year: i32,
) -> Result<i32, UnknownEraError> {
match era {
None => Ok(year),
Some("roc") => Ok(year),
Some("broc") => Ok(1 - year),
Some(b"roc") => Ok(year),
Some(b"broc") => Ok(1 - year),
Some(_) => Err(UnknownEraError),
}
}
Expand Down
2 changes: 1 addition & 1 deletion components/calendar/src/calendar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub trait Calendar: crate::cal::scaffold::UnstableSealed {
) -> Result<Self::DateInner, DateError> {
let mut fields = types::DateFields::default();
if era.is_some() {
fields.era = era;
fields.era = era.map(|e| e.as_bytes());
fields.era_year = Some(year);
} else {
fields.extended_year = Some(year);
Expand Down
2 changes: 1 addition & 1 deletion components/calendar/src/calendar_arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ pub(crate) trait DateFieldsResolver: Calendar {
/// this should always return an Err result.
fn year_info_from_era(
&self,
era: &str,
era: &[u8],
era_year: i32,
) -> Result<Self::YearInfo, UnknownEraError>;

Expand Down
4 changes: 2 additions & 2 deletions components/calendar/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ pub enum DateFromFieldsError {
/// use icu_calendar::types::DateFields;
///
/// let mut fields = DateFields::default();
/// fields.era = Some("reiwa");
/// fields.era = Some(b"reiwa");
/// fields.era_year = Some(6);
/// fields.ordinal_month = Some(1);
/// fields.day = Some(1);
Expand Down Expand Up @@ -277,7 +277,7 @@ pub enum DateFromFieldsError {
/// .expect_err("era year still needs an era");
/// assert!(matches!(err, DateFromFieldsError::NotEnoughFields));
///
/// fields.era = Some("am");
/// fields.era = Some(b"am");
///
/// let date = Date::try_from_fields(
/// fields,
Expand Down
2 changes: 1 addition & 1 deletion components/calendar/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ mod tests {

// A map from field names to a function that sets that field
let mut field_fns = BTreeMap::<&str, &dyn Fn(&mut DateFields)>::new();
field_fns.insert("era", &|fields| fields.era = Some("ad"));
field_fns.insert("era", &|fields| fields.era = Some(b"ad"));
field_fns.insert("era_year", &|fields| fields.era_year = Some(2000));
field_fns.insert("extended_year", &|fields| fields.extended_year = Some(2000));
field_fns.insert("month_code", &|fields| {
Expand Down
12 changes: 6 additions & 6 deletions components/calendar/src/tests/not_enough_fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn test_from_fields_not_enough_fields() {
assert_eq!(
Date::try_from_fields(
DateFields {
era: Some("hebrew"),
era: Some(b"hebrew"),
era_year: big_i32,
extended_year: None,
ordinal_month: None,
Expand All @@ -50,7 +50,7 @@ fn test_from_fields_not_enough_fields() {
assert_eq!(
Date::try_from_fields(
DateFields {
era: Some("hebrew"),
era: Some(b"hebrew"),
era_year: small_i32,
extended_year: None,
ordinal_month: None,
Expand Down Expand Up @@ -84,7 +84,7 @@ fn test_from_fields_not_enough_fields() {
assert_eq!(
Date::try_from_fields(
DateFields {
era: Some("hebrew"),
era: Some(b"hebrew"),
era_year: None,
extended_year: None,
ordinal_month: big_u8,
Expand All @@ -100,7 +100,7 @@ fn test_from_fields_not_enough_fields() {
assert_eq!(
Date::try_from_fields(
DateFields {
era: Some("hebrew"),
era: Some(b"hebrew"),
era_year: None,
extended_year: None,
ordinal_month: small_u8,
Expand Down Expand Up @@ -202,7 +202,7 @@ fn test_from_fields_not_enough_fields() {
assert_eq!(
Date::try_from_fields(
DateFields {
era: Some("hebrew"),
era: Some(b"hebrew"),
era_year: big_i32,
extended_year: None,
ordinal_month: small_u8,
Expand All @@ -218,7 +218,7 @@ fn test_from_fields_not_enough_fields() {
assert_eq!(
Date::try_from_fields(
DateFields {
era: Some("hebrew"),
era: Some(b"hebrew"),
era_year: small_i32,
extended_year: None,
ordinal_month: big_u8,
Expand Down
2 changes: 1 addition & 1 deletion components/calendar/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct DateFields<'a> {
/// The era code as defined by CLDR.
///
/// If set, [`Self::era_year`] must also be set.
pub era: Option<&'a str>,
pub era: Option<&'a [u8]>,
/// The numeric year in [`Self::era`].
///
/// If set, [`Self::era`] must also be set.
Expand Down
Loading