icu_datetime/provider/pattern/
hour_cycle.rs1#[cfg(feature = "datagen")]
6use super::runtime;
7use super::{reference, PatternItem};
8use crate::provider::fields;
9#[cfg(feature = "datagen")]
10use crate::provider::{self, skeleton};
11#[cfg(feature = "datagen")]
12use icu_locale_core::preferences::extensions::unicode::keywords::HourCycle;
13use icu_provider::prelude::*;
14
15#[derive(Debug, PartialEq, Clone, Copy, yoke::Yokeable, zerofrom::ZeroFrom)]
18#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
19#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::pattern))]
20#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
21#[allow(clippy::exhaustive_enums)] pub enum CoarseHourCycle {
23 H11H12,
25 H23,
27}
28
29impl Default for CoarseHourCycle {
32 fn default() -> Self {
33 CoarseHourCycle::H23
34 }
35}
36
37impl CoarseHourCycle {
38 pub fn determine(pattern: &reference::Pattern) -> Option<Self> {
41 for item in pattern.items.iter() {
42 if let PatternItem::Field(fields::Field {
43 symbol: fields::FieldSymbol::Hour(pattern_hour),
44 length: _,
45 }) = item
46 {
47 return Some(match pattern_hour {
48 fields::Hour::H11 | fields::Hour::H12 => CoarseHourCycle::H11H12,
49 fields::Hour::H23 => CoarseHourCycle::H23,
50 });
51 }
52 }
53
54 None
55 }
56
57 #[doc(hidden)]
60 #[cfg(feature = "datagen")]
61 pub fn apply_on_pattern<'data>(
62 &self,
63 date_time: &provider::calendar::patterns::GenericLengthPatterns<'data>,
64 skeletons: &provider::calendar::DateSkeletonPatterns<'data>,
65 pattern_str: &str,
66 mut pattern: reference::Pattern,
67 ) -> Option<reference::Pattern> {
68 for item in pattern.items_mut() {
69 if let PatternItem::Field(fields::Field { symbol, length: _ }) = item {
70 if let fields::FieldSymbol::Hour(pattern_hour) = symbol {
71 if match self {
72 CoarseHourCycle::H11H12 => match pattern_hour {
73 fields::Hour::H11 | fields::Hour::H12 => true,
74 fields::Hour::H23 => false,
75 },
76 CoarseHourCycle::H23 => match pattern_hour {
77 fields::Hour::H11 | fields::Hour::H12 => false,
78 fields::Hour::H23 => true,
79 },
80 } {
81 return Some(pattern_str.into());
84 } else {
85 *symbol = fields::FieldSymbol::Hour(match self {
87 CoarseHourCycle::H11H12 => fields::Hour::H12,
88 CoarseHourCycle::H23 => fields::Hour::H23,
89 });
90 break;
91 }
92 }
93 }
94 }
95
96 let skeleton = skeleton::reference::Skeleton::from(&pattern);
97
98 match skeleton::create_best_pattern_for_fields(
99 skeletons,
100 date_time,
101 skeleton.as_slice(),
102 &Default::default(),
103 true,
106 ) {
107 skeleton::BestSkeleton::AllFieldsMatch(patterns, _)
108 | skeleton::BestSkeleton::MissingOrExtraFields(patterns, _) => {
109 Some(reference::Pattern::from(&patterns.expect_pattern(
110 "Only week-of patterns have plural variants",
111 )))
112 }
113 skeleton::BestSkeleton::NoMatch => None,
114 }
115 }
116
117 pub fn invert(self) -> Self {
119 match self {
120 CoarseHourCycle::H11H12 => CoarseHourCycle::H23,
121 CoarseHourCycle::H23 => CoarseHourCycle::H11H12,
122 }
123 }
124}
125
126#[cfg(feature = "datagen")]
130pub(crate) fn naively_apply_preferences(
131 pattern: &mut runtime::Pattern,
132 hour_cycle: Option<HourCycle>,
133) {
134 if let Some(hour_cycle) = hour_cycle {
136 runtime::helpers::maybe_replace_first(pattern, |item| {
137 if let PatternItem::Field(fields::Field {
138 symbol: fields::FieldSymbol::Hour(current_hour),
139 length,
140 }) = item
141 {
142 let candidate_field = fields::Hour::from_hour_cycle(hour_cycle);
143 if *current_hour != candidate_field {
144 Some(PatternItem::from((
145 fields::FieldSymbol::Hour(candidate_field),
146 *length,
147 )))
148 } else {
149 None
150 }
151 } else {
152 None
153 }
154 });
155 }
156}