icu_datetime/provider/pattern/
hour_cycle.rs1#[cfg(feature = "datagen")]
6use super::runtime;
7use super::{PatternItem, reference};
8use crate::provider::fields;
9#[cfg(feature = "datagen")]
10use crate::provider::{
11 pattern::runtime::Pattern,
12 skeleton::{self, reference::Skeleton},
13};
14#[cfg(feature = "datagen")]
15use icu_locale_core::preferences::extensions::unicode::keywords::HourCycle;
16#[cfg(feature = "datagen")]
17use icu_plurals::PluralElements;
18use icu_provider::prelude::*;
19
20#[derive(Debug, PartialEq, Clone, Copy, yoke::Yokeable, zerofrom::ZeroFrom)]
23#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
24#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::pattern))]
25#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
26#[allow(clippy::exhaustive_enums)] pub enum CoarseHourCycle {
28 H11H12,
30 H23,
32}
33
34impl Default for CoarseHourCycle {
37 fn default() -> Self {
38 CoarseHourCycle::H23
39 }
40}
41
42impl CoarseHourCycle {
43 pub fn determine(pattern: &reference::Pattern) -> Option<Self> {
46 for item in pattern.items.iter() {
47 if let PatternItem::Field(fields::Field {
48 symbol: fields::FieldSymbol::Hour(pattern_hour),
49 length: _,
50 }) = item
51 {
52 return Some(match pattern_hour {
53 fields::Hour::H11 | fields::Hour::H12 => CoarseHourCycle::H11H12,
54 fields::Hour::H23 => CoarseHourCycle::H23,
55 });
56 }
57 }
58
59 None
60 }
61
62 #[doc(hidden)]
65 #[cfg(feature = "datagen")]
66 pub fn apply_on_pattern<'data>(
67 &self,
68 date_time: &skeleton::GenericLengthPatterns<'data>,
69 skeletons: &alloc::collections::BTreeMap<Skeleton, PluralElements<Pattern<'data>>>,
70 pattern_str: &str,
71 mut pattern: reference::Pattern,
72 ) -> Option<reference::Pattern> {
73 for item in pattern.items_mut() {
74 if let PatternItem::Field(fields::Field { symbol, length: _ }) = item
75 && let fields::FieldSymbol::Hour(pattern_hour) = symbol
76 {
77 if match self {
78 CoarseHourCycle::H11H12 => match pattern_hour {
79 fields::Hour::H11 | fields::Hour::H12 => true,
80 fields::Hour::H23 => false,
81 },
82 CoarseHourCycle::H23 => match pattern_hour {
83 fields::Hour::H11 | fields::Hour::H12 => false,
84 fields::Hour::H23 => true,
85 },
86 } {
87 return Some(pattern_str.into());
90 } else {
91 *symbol = fields::FieldSymbol::Hour(match self {
93 CoarseHourCycle::H11H12 => fields::Hour::H12,
94 CoarseHourCycle::H23 => fields::Hour::H23,
95 });
96 break;
97 }
98 }
99 }
100
101 let skeleton = Skeleton::from(&pattern);
102
103 match skeleton::create_best_pattern_for_fields(
104 skeletons,
105 date_time,
106 skeleton.as_slice(),
107 &Default::default(),
108 true,
111 ) {
112 skeleton::BestSkeleton::AllFieldsMatch(patterns, _)
113 | skeleton::BestSkeleton::MissingOrExtraFields(patterns, _) => {
114 Some(reference::Pattern::from(
115 #[allow(clippy::unwrap_used)] &patterns.try_into_other().unwrap(),
117 ))
118 }
119 skeleton::BestSkeleton::NoMatch => None,
120 }
121 }
122
123 pub fn invert(self) -> Self {
125 match self {
126 CoarseHourCycle::H11H12 => CoarseHourCycle::H23,
127 CoarseHourCycle::H23 => CoarseHourCycle::H11H12,
128 }
129 }
130}
131
132#[cfg(feature = "datagen")]
136pub(crate) fn naively_apply_hour_cycle(pattern: &mut Pattern, hour_cycle: Option<HourCycle>) {
137 if let Some(hour_cycle) = hour_cycle {
139 runtime::helpers::maybe_replace_first(pattern, |item| {
140 if let PatternItem::Field(fields::Field {
141 symbol: fields::FieldSymbol::Hour(current_hour),
142 length,
143 }) = item
144 {
145 let candidate_field = match hour_cycle {
146 HourCycle::H11 => fields::Hour::H11,
147 HourCycle::H12 => fields::Hour::H12,
148 HourCycle::H23 => fields::Hour::H23,
149 _ => unreachable!(),
150 };
151 if *current_hour != candidate_field {
152 Some(PatternItem::from((
153 fields::FieldSymbol::Hour(candidate_field),
154 *length,
155 )))
156 } else {
157 None
158 }
159 } else {
160 None
161 }
162 });
163 }
164}