icu_datetime/provider/pattern/
mod.rs

1// This file is part of ICU4X. For terms of use, please see the file
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//! Structured datetime pattern types for datagen and the data provider.
6//!
7//! <div class="stab unstable">
8//! 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
9//! including in SemVer minor releases. While the serde representation of data structs is guaranteed
10//! to be stable, their Rust representation might not be. Use with caution.
11//! </div>
12
13mod common;
14mod error;
15mod hour_cycle;
16mod item;
17pub mod reference;
18pub mod runtime;
19
20use crate::provider::fields;
21pub use error::PatternError;
22#[cfg(feature = "datagen")]
23pub(crate) use hour_cycle::naively_apply_preferences;
24pub use hour_cycle::CoarseHourCycle;
25use icu_provider::prelude::*;
26pub use item::{GenericPatternItem, PatternItem};
27
28/// The granularity of time represented in a [`Pattern`](runtime::Pattern).
29/// Ordered from least granular to most granular for comparison.
30#[derive(
31    Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, yoke::Yokeable, zerofrom::ZeroFrom,
32)]
33#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
34#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::pattern))]
35#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
36#[non_exhaustive]
37pub enum TimeGranularity {
38    /// No time is in the pattern.
39    None,
40    /// Smallest time unit = hours.
41    Hours,
42    /// Smallest time unit = minutes.
43    Minutes,
44    /// Smallest time unit = seconds.
45    Seconds,
46    /// Smallest time unit = Nanoseconds.
47    Nanoseconds,
48}
49
50impl Default for TimeGranularity {
51    fn default() -> Self {
52        Self::None
53    }
54}
55
56impl TimeGranularity {
57    /// Returns [`true`] if the most granular time being displayed will align with
58    /// the top of the hour, otherwise returns [`false`].
59    /// e.g. `12:00:00` is at the top of the hour for any display granularity.
60    /// e.g. `12:00:05` is only at the top of the hour if the seconds are not displayed.
61    pub fn is_top_of_hour(self, minute: u8, second: u8, subsecond: u32) -> bool {
62        match self {
63            Self::None | Self::Hours => true,
64            Self::Minutes => minute == 0,
65            Self::Seconds => minute == 0 && second == 0,
66            Self::Nanoseconds => minute == 0 && second == 0 && subsecond == 0,
67        }
68    }
69
70    #[inline]
71    pub(crate) fn from_ordinal(ordinal: u8) -> TimeGranularity {
72        use TimeGranularity::*;
73        match ordinal {
74            1 => Hours,
75            2 => Minutes,
76            3 => Seconds,
77            4 => Nanoseconds,
78            _ => None,
79        }
80    }
81
82    #[inline]
83    pub(crate) const fn ordinal(self) -> u8 {
84        use TimeGranularity::*;
85        match self {
86            None => 0,
87            Hours => 1,
88            Minutes => 2,
89            Seconds => 3,
90            Nanoseconds => 4,
91        }
92    }
93}
94
95impl From<PatternItem> for TimeGranularity {
96    /// Retrieves the granularity of time represented by a [`PatternItem`].
97    /// If the [`PatternItem`] is not time-related, returns [`None`].
98    fn from(item: PatternItem) -> Self {
99        match item {
100            PatternItem::Field(field) => match field.symbol {
101                fields::FieldSymbol::Hour(_) => Self::Hours,
102                fields::FieldSymbol::Minute => Self::Minutes,
103                fields::FieldSymbol::Second(_) => Self::Seconds,
104                fields::FieldSymbol::DecimalSecond(_) => Self::Nanoseconds,
105                _ => Self::None,
106            },
107            _ => Self::None,
108        }
109    }
110}