• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zbraniecki / icu4x / 9207498870

23 May 2024 07:11AM UTC coverage: 76.113% (-0.3%) from 76.402%
9207498870

push

github

web-flow
Add to `IsoDurationParser` documentation in `ixdtf` (#4916)

53397 of 70155 relevant lines covered (76.11%)

514353.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.42
/components/datetime/src/pattern/hour_cycle.rs
1
// This file is part of ICU4X. For terms of use, please see the file
14,408✔
2
// called LICENSE at the top level of the ICU4X source tree
3
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4

5
use super::{reference, runtime, PatternItem};
6
use crate::{fields, options::preferences};
7
#[cfg(feature = "datagen")]
8
use crate::{provider, skeleton};
9
use icu_provider::prelude::*;
10

11
/// Used to represent either H11/H12, or H23/H24. Skeletons only store these
12
/// hour cycles as H12 or H23.
13
#[derive(Debug, PartialEq, Clone, Copy, yoke::Yokeable, zerofrom::ZeroFrom)]
14,447✔
14
#[cfg_attr(
15
    feature = "datagen",
16
    derive(serde::Serialize, databake::Bake),
18✔
17
    databake(path = icu_datetime::pattern),
18
)]
19
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
80✔
20
#[allow(clippy::exhaustive_enums)] // this type is stable
21
pub enum CoarseHourCycle {
20✔
22
    /// Can either be fields::Hour::H11 or fields::Hour::H12
23
    H11H12,
24
    /// Can either be fields::Hour::H23 or fields::Hour::H24
25
    H23H24,
26
}
27

28
/// Default is required for serialization. H23H24 is the more locale-agnostic choice, as it's
29
/// less likely to have a day period in it.
30
impl Default for CoarseHourCycle {
31
    fn default() -> Self {
×
32
        CoarseHourCycle::H23H24
×
33
    }
×
34
}
35

36
impl CoarseHourCycle {
37
    /// Figure out the coarse hour cycle given a pattern, which is useful for generating the provider
38
    /// patterns for `length::Bag`.
39
    pub fn determine(pattern: &reference::Pattern) -> Option<Self> {
14,408✔
40
        for item in pattern.items.iter() {
14,408✔
41
            if let PatternItem::Field(fields::Field {
14,408✔
42
                symbol: fields::FieldSymbol::Hour(pattern_hour),
14,408✔
43
                length: _,
44
            }) = item
45
            {
46
                return Some(match pattern_hour {
28,816✔
47
                    fields::Hour::H11 | fields::Hour::H12 => CoarseHourCycle::H11H12,
6,404✔
48
                    fields::Hour::H23 | fields::Hour::H24 => CoarseHourCycle::H23H24,
8,004✔
49
                });
50
            }
51
        }
52

53
        None
×
54
    }
14,408✔
55

56
    /// Invoke the pattern matching machinery to transform the hour cycle of a pattern. This provides
57
    /// a safe mapping from a h11/h12 to h23/h24 for transforms.
58
    #[doc(hidden)]
59
    #[cfg(feature = "datagen")]
60
    pub fn apply_on_pattern<'data>(
14,410✔
61
        &self,
62
        date_time: &provider::calendar::patterns::GenericLengthPatternsV1<'data>,
63
        skeletons: &provider::calendar::DateSkeletonPatternsV1<'data>,
64
        pattern_str: &str,
65
        mut pattern: reference::Pattern,
66
    ) -> Option<reference::Pattern> {
67
        for item in pattern.items_mut() {
14,410✔
68
            if let PatternItem::Field(fields::Field { symbol, length: _ }) = item {
14,408✔
69
                if let fields::FieldSymbol::Hour(pattern_hour) = symbol {
14,408✔
70
                    if match self {
28,816✔
71
                        CoarseHourCycle::H11H12 => match pattern_hour {
8,004✔
72
                            fields::Hour::H11 | fields::Hour::H12 => true,
×
73
                            fields::Hour::H23 | fields::Hour::H24 => false,
8,004✔
74
                        },
75
                        CoarseHourCycle::H23H24 => match pattern_hour {
6,404✔
76
                            fields::Hour::H11 | fields::Hour::H12 => false,
6,404✔
77
                            fields::Hour::H23 | fields::Hour::H24 => true,
×
78
                        },
79
                    } {
80
                        // The preference hour cycle matches the pattern, bail out early and
81
                        // return the current pattern.
82
                        return Some(pattern_str.into());
×
83
                    } else {
84
                        // Mutate the pattern with the new symbol, so that it can be matched against.
85
                        *symbol = fields::FieldSymbol::Hour(match self {
28,816✔
86
                            CoarseHourCycle::H11H12 => fields::Hour::H12,
8,004✔
87
                            CoarseHourCycle::H23H24 => fields::Hour::H23,
6,404✔
88
                        });
89
                        break;
90
                    }
91
                }
92
            }
93
        }
94

95
        let skeleton = skeleton::reference::Skeleton::from(&pattern);
14,412✔
96

97
        match skeleton::create_best_pattern_for_fields(
14,407✔
98
            skeletons,
99
            date_time,
100
            skeleton.as_slice(),
14,410✔
101
            &Default::default(),
14,408✔
102
            // Prefer using the matched pattern directly, rather than mutating it to match the
103
            // requested fields.
104
            true,
105
        ) {
106
            skeleton::BestSkeleton::AllFieldsMatch(patterns)
14,408✔
107
            | skeleton::BestSkeleton::MissingOrExtraFields(patterns) => {
×
108
                Some(reference::Pattern::from(&patterns.expect_pattern(
14,408✔
109
                    "Only week-of patterns have plural variants",
110
                )))
111
            }
14,407✔
112
            skeleton::BestSkeleton::NoMatch => None,
×
113
        }
114
    }
14,406✔
115

116
    /// Get the other coarse hour cycle (map h11/h12 to h23/h24, and vice versa)
117
    pub fn invert(self) -> Self {
×
118
        match self {
×
119
            CoarseHourCycle::H11H12 => CoarseHourCycle::H23H24,
×
120
            CoarseHourCycle::H23H24 => CoarseHourCycle::H11H12,
×
121
        }
122
    }
×
123
}
124

125
/// The hour cycle can be set by preferences. This function switches between h11 and h12,
126
/// and between h23 and h24. This function is naive as it is assumed that this application of
127
/// the hour cycle will not change between h1x to h2x.
128
pub(crate) fn naively_apply_preferences(
25,831✔
129
    pattern: &mut runtime::Pattern,
130
    preferences: &Option<preferences::Bag>,
131
) {
132
    // If there is a preference overriding the hour cycle, apply it now.
133
    if let Some(preferences::Bag {
25,831✔
134
        hour_cycle: Some(hour_cycle),
74✔
135
    }) = preferences
136
    {
137
        runtime::helpers::maybe_replace_first(pattern, |item| {
342✔
138
            if let PatternItem::Field(fields::Field {
268✔
139
                symbol: fields::FieldSymbol::Hour(current_hour),
74✔
140
                length,
74✔
141
            }) = item
142
            {
143
                if *current_hour != hour_cycle.field() {
74✔
144
                    Some(PatternItem::from((
25✔
145
                        fields::FieldSymbol::Hour(hour_cycle.field()),
25✔
146
                        *length,
25✔
147
                    )))
148
                } else {
149
                    None
49✔
150
                }
151
            } else {
152
                None
194✔
153
            }
154
        });
268✔
155
    }
156
}
25,831✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc