#[cfg(feature = "datagen")]
use super::runtime;
use super::{reference, PatternItem};
use crate::provider::fields;
#[cfg(feature = "datagen")]
use crate::provider::{
pattern::runtime::Pattern,
skeleton::{self, reference::Skeleton},
};
#[cfg(feature = "datagen")]
use icu_locale_core::preferences::extensions::unicode::keywords::HourCycle;
#[cfg(feature = "datagen")]
use icu_plurals::PluralElements;
use icu_provider::prelude::*;
#[derive(Debug, PartialEq, Clone, Copy, yoke::Yokeable, zerofrom::ZeroFrom)]
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::pattern))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[allow(clippy::exhaustive_enums)] pub enum CoarseHourCycle {
H11H12,
H23,
}
impl Default for CoarseHourCycle {
fn default() -> Self {
CoarseHourCycle::H23
}
}
impl CoarseHourCycle {
pub fn determine(pattern: &reference::Pattern) -> Option<Self> {
for item in pattern.items.iter() {
if let PatternItem::Field(fields::Field {
symbol: fields::FieldSymbol::Hour(pattern_hour),
length: _,
}) = item
{
return Some(match pattern_hour {
fields::Hour::H11 | fields::Hour::H12 => CoarseHourCycle::H11H12,
fields::Hour::H23 => CoarseHourCycle::H23,
});
}
}
None
}
#[doc(hidden)]
#[cfg(feature = "datagen")]
pub fn apply_on_pattern<'data>(
&self,
date_time: &skeleton::GenericLengthPatterns<'data>,
skeletons: &alloc::collections::BTreeMap<Skeleton, PluralElements<Pattern<'data>>>,
pattern_str: &str,
mut pattern: reference::Pattern,
) -> Option<reference::Pattern> {
for item in pattern.items_mut() {
if let PatternItem::Field(fields::Field { symbol, length: _ }) = item {
if let fields::FieldSymbol::Hour(pattern_hour) = symbol {
if match self {
CoarseHourCycle::H11H12 => match pattern_hour {
fields::Hour::H11 | fields::Hour::H12 => true,
fields::Hour::H23 => false,
},
CoarseHourCycle::H23 => match pattern_hour {
fields::Hour::H11 | fields::Hour::H12 => false,
fields::Hour::H23 => true,
},
} {
return Some(pattern_str.into());
} else {
*symbol = fields::FieldSymbol::Hour(match self {
CoarseHourCycle::H11H12 => fields::Hour::H12,
CoarseHourCycle::H23 => fields::Hour::H23,
});
break;
}
}
}
}
let skeleton = Skeleton::from(&pattern);
match skeleton::create_best_pattern_for_fields(
skeletons,
date_time,
skeleton.as_slice(),
&Default::default(),
true,
) {
skeleton::BestSkeleton::AllFieldsMatch(patterns, _)
| skeleton::BestSkeleton::MissingOrExtraFields(patterns, _) => {
Some(reference::Pattern::from(
#[allow(clippy::unwrap_used)] &patterns.try_into_other().unwrap(),
))
}
skeleton::BestSkeleton::NoMatch => None,
}
}
pub fn invert(self) -> Self {
match self {
CoarseHourCycle::H11H12 => CoarseHourCycle::H23,
CoarseHourCycle::H23 => CoarseHourCycle::H11H12,
}
}
}
#[cfg(feature = "datagen")]
pub(crate) fn naively_apply_hour_cycle(pattern: &mut Pattern, hour_cycle: Option<HourCycle>) {
if let Some(hour_cycle) = hour_cycle {
runtime::helpers::maybe_replace_first(pattern, |item| {
if let PatternItem::Field(fields::Field {
symbol: fields::FieldSymbol::Hour(current_hour),
length,
}) = item
{
let candidate_field = match hour_cycle {
HourCycle::H11 => fields::Hour::H11,
HourCycle::H12 => fields::Hour::H12,
HourCycle::H23 => fields::Hour::H23,
_ => unreachable!(),
};
if *current_hour != candidate_field {
Some(PatternItem::from((
fields::FieldSymbol::Hour(candidate_field),
*length,
)))
} else {
None
}
} else {
None
}
});
}
}