1use crate::time::{CalendarDate, CalendarDateTime, HourOfDay, MinuteOfHour};
2
3#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Hash)]
4pub struct TimeOfDay {
5 hour: HourOfDay,
6 minute: MinuteOfHour,
7}
8
9impl From<(u32, u32)> for TimeOfDay {
10 fn from((hour, minute): (u32, u32)) -> Self {
11 TimeOfDay::new(HourOfDay::new(hour), MinuteOfHour::new(minute))
12 }
13}
14
15impl TimeOfDay {
16 pub fn new(hour: HourOfDay, minute: MinuteOfHour) -> Self {
17 Self { hour, minute }
18 }
19
20 pub fn breach_encapsulation_of_hour(&self) -> &HourOfDay {
21 &self.hour
22 }
23
24 pub fn breach_encapsulation_of_minute(&self) -> &MinuteOfHour {
25 &self.minute
26 }
27
28 pub fn on(self, date: CalendarDate) -> CalendarDateTime {
29 CalendarDateTime::new(date, self)
30 }
31
32 pub fn is_after(&self, other: &Self) -> bool {
33 !self.is_before(other) && self != other
34 }
35
36 pub fn is_before(&self, other: &Self) -> bool {
37 self.hour.is_before(&other.hour)
38 || (self.hour == other.hour && self.minute.is_before(&other.minute))
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 extern crate once_cell;
45
46 use std::collections::hash_map::DefaultHasher;
47 use std::hash::{Hash, Hasher};
48
49 use once_cell::sync::Lazy;
50
51 use crate::time::{CalendarDate, CalendarDateTime, HourOfDay, MinuteOfHour, TimeOfDay};
52
53 static FEB17: Lazy<CalendarDate> = Lazy::new(|| CalendarDate::from((2006, 2, 17)));
54 static MIDNIGHT: Lazy<TimeOfDay> = Lazy::new(|| TimeOfDay::from((0, 0)));
55 static MORNING: Lazy<TimeOfDay> = Lazy::new(|| TimeOfDay::from((10, 20)));
56 static NOON: Lazy<TimeOfDay> = Lazy::new(|| TimeOfDay::from((12, 0)));
57 static AFTERNOON: Lazy<TimeOfDay> = Lazy::new(|| TimeOfDay::from((15, 40)));
58 static TWO_MINUTES_BEFORE_MIDNIGHT: Lazy<TimeOfDay> = Lazy::new(|| TimeOfDay::from((23, 58)));
59 static TEN_MINUTES_BEFORE_MIDNIGHT: Lazy<TimeOfDay> = Lazy::new(|| TimeOfDay::from((23, 50)));
60
61 #[test]
62 fn test01_on_start_of_day() {
63 let feb17at_start_of_day = CalendarDateTime::from((2006, 2, 17, 0, 0));
64 assert_eq!(MIDNIGHT.clone().on(FEB17.clone()), feb17at_start_of_day)
65 }
66
67 #[test]
68 fn test02_on_middle_of_day() {
69 let feb17at_middle_of_day = CalendarDateTime::from((2006, 2, 17, 12, 0));
70 assert_eq!(NOON.clone().on(FEB17.clone()), feb17at_middle_of_day)
71 }
72
73 #[test]
74 fn test03_on_end_of_day() {
75 let feb17at_end_of_day = CalendarDateTime::from((2006, 2, 17, 23, 58));
76 assert_eq!(
77 TWO_MINUTES_BEFORE_MIDNIGHT.clone().on(FEB17.clone()),
78 feb17at_end_of_day
79 )
80 }
81
82 #[test]
83 fn test04_equals() {
84 assert_eq!(MIDNIGHT.clone(), TimeOfDay::from((0, 0)));
85 assert_eq!(MORNING.clone(), TimeOfDay::from((10, 20)));
86 assert_eq!(NOON.clone(), TimeOfDay::from((12, 0)));
87 assert_eq!(AFTERNOON.clone(), TimeOfDay::from((15, 40)));
88 assert_eq!(
89 TWO_MINUTES_BEFORE_MIDNIGHT.clone(),
90 TimeOfDay::from((23, 58))
91 );
92 assert_ne!(MIDNIGHT.clone(), MORNING.clone());
93 assert_ne!(
94 TEN_MINUTES_BEFORE_MIDNIGHT.clone(),
95 TWO_MINUTES_BEFORE_MIDNIGHT.clone()
96 );
97 assert_eq!(
98 NOON.clone(),
99 TimeOfDay::new(HourOfDay::new(12), MinuteOfHour::new(0))
100 );
101 }
104
105 #[test]
106 fn test05_hash_code() {
107 let mut hasher1 = DefaultHasher::new();
108 MIDNIGHT.clone().hash(&mut hasher1);
109 let hash1 = hasher1.finish();
110 let mut hasher2 = DefaultHasher::new();
111 TimeOfDay::from((0, 0)).hash(&mut hasher2);
112 let hash2 = hasher2.finish();
113 assert_eq!(hash1, hash2);
114
115 let mut hasher1 = DefaultHasher::new();
116 MORNING.clone().hash(&mut hasher1);
117 let hash1 = hasher1.finish();
118 let mut hasher2 = DefaultHasher::new();
119 TimeOfDay::from((10, 20)).hash(&mut hasher2);
120 let hash2 = hasher2.finish();
121 assert_eq!(hash1, hash2);
122
123 let mut hasher1 = DefaultHasher::new();
124 NOON.clone().hash(&mut hasher1);
125 let hash1 = hasher1.finish();
126 let mut hasher2 = DefaultHasher::new();
127 TimeOfDay::from((12, 0)).hash(&mut hasher2);
128 let hash2 = hasher2.finish();
129 assert_eq!(hash1, hash2);
130
131 let mut hasher1 = DefaultHasher::new();
132 AFTERNOON.clone().hash(&mut hasher1);
133 let hash1 = hasher1.finish();
134 let mut hasher2 = DefaultHasher::new();
135 TimeOfDay::from((15, 40)).hash(&mut hasher2);
136 let hash2 = hasher2.finish();
137 assert_eq!(hash1, hash2);
138
139 let mut hasher1 = DefaultHasher::new();
140 TWO_MINUTES_BEFORE_MIDNIGHT.clone().hash(&mut hasher1);
141 let hash1 = hasher1.finish();
142 let mut hasher2 = DefaultHasher::new();
143 TimeOfDay::from((23, 58)).hash(&mut hasher2);
144 let hash2 = hasher2.finish();
145 assert_eq!(hash1, hash2);
146 }
147
148 #[test]
149 fn test06_after_with_earlier_time_of_day() {
150 assert!(
151 TWO_MINUTES_BEFORE_MIDNIGHT.is_after(&MIDNIGHT),
152 "expected TWO_MINUTES_BEFORE_MIDNIGHT to be after MIDNIGHT"
153 );
154 assert!(
155 AFTERNOON.is_after(&MORNING),
156 "expected AFTERNOON to be after MORNING"
157 );
158 assert!(
159 NOON.is_after(&MIDNIGHT),
160 "expected NOON to be after MIDNIGHT"
161 );
162 }
163
164 #[test]
165 fn test07_after_with_later_time_of_day() {
166 assert_eq!(
167 MIDNIGHT.is_after(&TWO_MINUTES_BEFORE_MIDNIGHT),
168 false,
169 "expected MIDNIGHT not after TWO_MINUTES_BEFORE_MIDNIGHT"
170 );
171 assert_eq!(
172 MORNING.is_after(&AFTERNOON),
173 false,
174 "expected MORNING not after AFTERNOON"
175 );
176 assert_eq!(
177 NOON.is_after(&TWO_MINUTES_BEFORE_MIDNIGHT),
178 false,
179 "expected NOON not after TWO_MINUTES_BEFORE_MIDNIGHT"
180 )
181 }
182
183 #[test]
184 fn test08_after_with_same_time_of_day() {
185 assert_eq!(
186 MIDNIGHT.is_after(&MIDNIGHT),
187 false,
188 "expected MIDNIGHT not after MIDNIGHT"
189 );
190 assert_eq!(
191 MIDNIGHT.lt(&MIDNIGHT),
192 false,
193 "expected MIDNIGHT not after MIDNIGHT"
194 );
195 assert_eq!(
196 MORNING.is_after(&MORNING),
197 false,
198 "expected MORNING not after MORNING"
199 );
200 assert_eq!(
201 MORNING.lt(&MORNING),
202 false,
203 "expected MORNING not after MORNING"
204 );
205 assert_eq!(
206 AFTERNOON.is_after(&AFTERNOON),
207 false,
208 "expected AFTERNOON not after AFTERNOON"
209 );
210 assert_eq!(
211 AFTERNOON.lt(&AFTERNOON),
212 false,
213 "expected AFTERNOON not after AFTERNOON"
214 );
215 assert_eq!(NOON.is_after(&NOON), false, "expected NOON not after NOON");
216 assert_eq!(NOON.lt(&NOON), false, "expected NOON not after NOON");
217 }
218
219 #[test]
220 fn test09_before_with_earlier_time_of_day() {
221 assert_eq!(
222 TWO_MINUTES_BEFORE_MIDNIGHT.is_before(&MIDNIGHT),
223 false,
224 "expected twoMinutesBeforeMidnight not after midnight"
225 );
226 assert_eq!(
227 AFTERNOON.is_before(&MORNING),
228 false,
229 "expected afternoon not after morning"
230 );
231 assert_eq!(
232 NOON.is_before(&MIDNIGHT),
233 false,
234 "expected noon not after midnight"
235 );
236 }
237
238 #[test]
239 fn test10_before_with_later_time_of_day() {
240 assert!(
241 MIDNIGHT.is_before(&TWO_MINUTES_BEFORE_MIDNIGHT),
242 "expected midnight not after twoMinutesBeforeMidnight"
243 );
244 assert!(
245 MORNING.is_before(&AFTERNOON),
246 "expected morning not after afternoon"
247 );
248 assert!(
249 NOON.is_before(&TWO_MINUTES_BEFORE_MIDNIGHT),
250 "expected noon not after twoMinutesBeforeMidnight"
251 );
252 }
253
254 fn test11_before_with_same_time_of_day() {
255 assert!(
256 !MIDNIGHT.is_before(&MIDNIGHT),
257 "expected midnight not after midnight"
258 );
259 assert!(
260 !MORNING.is_before(&MORNING),
261 "expected morning not after morning"
262 );
263 assert!(
264 !AFTERNOON.is_before(&AFTERNOON),
265 "expected afternoon not after afternoon"
266 );
267 assert!(!NOON.is_before(&NOON), "expected NOON not after NOON");
268 }
269
270 #[test]
271 fn test12_get_hour() {
272 assert_eq!(*MIDNIGHT.breach_encapsulation_of_hour(), HourOfDay::new(0));
273 assert_eq!(*MORNING.breach_encapsulation_of_hour(), HourOfDay::new(10));
274 assert_eq!(*NOON.breach_encapsulation_of_hour(), HourOfDay::new(12));
275 assert_eq!(
276 *AFTERNOON.breach_encapsulation_of_hour(),
277 HourOfDay::new(15)
278 );
279 assert_eq!(
280 *TWO_MINUTES_BEFORE_MIDNIGHT.breach_encapsulation_of_hour(),
281 HourOfDay::new(23)
282 );
283 }
284
285 #[test]
286 fn test13_get_minute() {
287 assert_eq!(
288 *MIDNIGHT.breach_encapsulation_of_minute(),
289 MinuteOfHour::new(0)
290 );
291 assert_eq!(
292 *MORNING.breach_encapsulation_of_minute(),
293 MinuteOfHour::new(20)
294 );
295 assert_eq!(*NOON.breach_encapsulation_of_minute(), MinuteOfHour::new(0));
296 assert_eq!(
297 *AFTERNOON.breach_encapsulation_of_minute(),
298 MinuteOfHour::new(40)
299 );
300 assert_eq!(
301 *TWO_MINUTES_BEFORE_MIDNIGHT.breach_encapsulation_of_minute(),
302 MinuteOfHour::new(58)
303 );
304 }
305
306 }