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}