chinese_format/gregorian/time/
delta.rs

1use super::{Hour12, Minute};
2use crate::{chinese_vec, Chinese, ChineseFormat, Variant};
3
4/// Time expressed as minutes (a *delta*) past/to an hour.
5///
6/// Traditionally, it supports a minimalist 12-hour format.
7///
8/// ```
9/// use chinese_format::{*, gregorian::*};
10///
11/// # fn main() -> GenericResult<()> {
12/// let o_clock = DeltaTime {
13///     hour: 6.try_into()?,
14///     minute: 0.try_into()?,
15///     formal: false
16/// };
17/// assert_eq!(o_clock.to_chinese(Variant::Simplified), "六点钟");
18/// assert_eq!(o_clock.to_chinese(Variant::Traditional), "六點鐘");
19///
20/// let past_one = DeltaTime {
21///     hour: 6.try_into()?,
22///     minute: 1.try_into()?,
23///     formal: false
24/// };
25/// assert_eq!(past_one.to_chinese(Variant::Simplified), "六点过一分");
26/// assert_eq!(past_one.to_chinese(Variant::Traditional), "六點過一分");
27///
28/// let past_five = DeltaTime {
29///     hour: 6.try_into()?,
30///     minute: 5.try_into()?,
31///     formal: false
32/// };
33/// assert_eq!(past_five.to_chinese(Variant::Simplified), "六点过五分");
34/// assert_eq!(past_five.to_chinese(Variant::Traditional), "六點過五分");
35///
36/// let past_fourteen = DeltaTime {
37///     hour: 6.try_into()?,
38///     minute: 14.try_into()?,
39///     formal: false
40/// };
41/// assert_eq!(past_fourteen.to_chinese(Variant::Simplified), "六点过十四分");
42/// assert_eq!(past_fourteen.to_chinese(Variant::Traditional), "六點過十四分");
43///
44/// let quarter = DeltaTime {
45///     hour: 6.try_into()?,
46///     minute: 15.try_into()?,
47///     formal: false
48/// };
49/// assert_eq!(quarter.to_chinese(Variant::Simplified), "六点刻");
50/// assert_eq!(quarter.to_chinese(Variant::Traditional), "六點刻");
51///
52/// let past_sixteen = DeltaTime {
53///     hour: 6.try_into()?,
54///     minute: 16.try_into()?,
55///     formal: false
56/// };
57/// assert_eq!(past_sixteen.to_chinese(Variant::Simplified), "六点过十六分");
58/// assert_eq!(past_sixteen.to_chinese(Variant::Traditional), "六點過十六分");
59///
60/// let past_twenty_nine = DeltaTime {
61///     hour: 6.try_into()?,
62///     minute: 29.try_into()?,
63///     formal: false
64/// };
65/// assert_eq!(past_twenty_nine.to_chinese(Variant::Simplified), "六点过二十九分");
66/// assert_eq!(past_twenty_nine.to_chinese(Variant::Traditional), "六點過二十九分");
67///
68/// let half = DeltaTime {
69///     hour: 6.try_into()?,
70///     minute: 30.try_into()?,
71///     formal: false
72/// };
73/// assert_eq!(half.to_chinese(Variant::Simplified), "六点半");
74/// assert_eq!(half.to_chinese(Variant::Traditional), "六點半");
75///
76/// let twenty_nine_to = DeltaTime {
77///     hour: 6.try_into()?,
78///     minute: 31.try_into()?,
79///     formal: false
80/// };
81/// assert_eq!(twenty_nine_to.to_chinese(Variant::Simplified), "七点差二十九分");
82/// assert_eq!(twenty_nine_to.to_chinese(Variant::Traditional), "七點差二十九分");
83///
84/// let sixteen_to = DeltaTime {
85///     hour: 6.try_into()?,
86///     minute: 44.try_into()?,
87///     formal: false
88/// };
89/// assert_eq!(sixteen_to.to_chinese(Variant::Simplified), "七点差十六分");
90/// assert_eq!(sixteen_to.to_chinese(Variant::Traditional), "七點差十六分");
91///
92/// let three_quarters = DeltaTime {
93///     hour: 6.try_into()?,
94///     minute: 45.try_into()?,
95///     formal: false
96/// };
97/// assert_eq!(three_quarters.to_chinese(Variant::Simplified), "六点三刻");
98/// assert_eq!(three_quarters.to_chinese(Variant::Traditional), "六點三刻");
99///
100/// let fourteen_to = DeltaTime {
101///     hour: 6.try_into()?,
102///     minute: 46.try_into()?,
103///     formal: false
104/// };
105/// assert_eq!(fourteen_to.to_chinese(Variant::Simplified), "七点差十四分");
106/// assert_eq!(fourteen_to.to_chinese(Variant::Traditional), "七點差十四分");
107///
108/// let one_to = DeltaTime {
109///     hour: 6.try_into()?,
110///     minute: 59.try_into()?,
111///     formal: false
112/// };
113/// assert_eq!(one_to.to_chinese(Variant::Simplified), "七点差一分");
114/// assert_eq!(one_to.to_chinese(Variant::Traditional), "七點差一分");
115///
116/// # Ok(())
117/// # }
118/// ```
119///
120/// In formal style, 差 is placed *before* the hour expression, while 过 remains at its place:
121///
122/// ```
123/// use chinese_format::{*, gregorian::*};
124///
125/// # fn main() -> GenericResult<()> {
126/// let past_sixteen = DeltaTime {
127///     hour: 6.try_into()?,
128///     minute: 16.try_into()?,
129///     formal: true
130/// };
131/// assert_eq!(past_sixteen.to_chinese(Variant::Simplified), "六点过十六分");
132/// assert_eq!(past_sixteen.to_chinese(Variant::Traditional), "六點過十六分");
133///
134///
135/// let fourteen_to = DeltaTime {
136///     hour: 6.try_into()?,
137///     minute: 46.try_into()?,
138///     formal: true
139/// };
140/// assert_eq!(fourteen_to.to_chinese(Variant::Simplified), "差十四分七点");
141/// assert_eq!(fourteen_to.to_chinese(Variant::Traditional), "差十四分七點");
142/// # Ok(())
143/// # }
144/// ```
145#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
146pub struct DeltaTime {
147    /// The hour, as displayed by the *hour* hand of an analog clock.
148    pub hour: Hour12,
149
150    /// The minute, as displayed by the *minute* hand of an analog clock.
151    pub minute: Minute,
152
153    /// Whether the time should be expressed in a formal way.
154    pub formal: bool,
155}
156
157const ZHONG: (&str, &str) = ("钟", "鐘");
158
159const GUO: (&str, &str) = ("过", "過");
160
161const KE: &str = "刻";
162
163const BAN: &str = "半";
164
165const CHA: &str = "差";
166
167impl ChineseFormat for DeltaTime {
168    fn to_chinese(&self, variant: Variant) -> Chinese {
169        match self.minute.into() {
170            0 => chinese_vec!(variant, [self.hour, ZHONG]),
171
172            1..=14 | 16..=29 => chinese_vec!(variant, [self.hour, GUO, self.minute]),
173
174            15 => chinese_vec!(variant, [self.hour, KE]),
175
176            30 => chinese_vec!(variant, [self.hour, BAN]),
177
178            45 => chinese_vec!(variant, [self.hour, 3, KE]),
179
180            _ => {
181                let minute_complement = self.minute.complement().expect("0 is not in this range");
182
183                if self.formal {
184                    chinese_vec!(variant, [CHA, minute_complement, self.hour.next()])
185                } else {
186                    chinese_vec!(variant, [self.hour.next(), CHA, minute_complement])
187                }
188            }
189        }
190        .collect()
191    }
192}