/rust/registry/src/index.crates.io-6f17d22bba15001f/jiff-0.2.5/src/civil/weekday.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use crate::{ |
2 | | error::Error, |
3 | | shared::util::itime::IWeekday, |
4 | | util::{ |
5 | | rangeint::{RFrom, RInto}, |
6 | | t::{self, C}, |
7 | | }, |
8 | | }; |
9 | | |
10 | | /// A representation for the day of the week. |
11 | | /// |
12 | | /// The default representation follows ISO 8601. That is, the week starts with |
13 | | /// Monday and numbering starts at `1`. However, the various constructors and |
14 | | /// accessors support using other schemes in wide use: |
15 | | /// |
16 | | /// * [`Weekday::from_monday_zero_offset`] builds a weekday from |
17 | | /// a scheme that starts the week on Monday at offset `0`, while |
18 | | /// [`Weekday::to_monday_zero_offset`] converts to it. |
19 | | /// * [`Weekday::from_monday_one_offset`] builds a weekday from a scheme |
20 | | /// that starts the week on Monday at offset `1` (the default representation), |
21 | | /// while [`Weekday::to_monday_one_offset`] converts to it. |
22 | | /// * [`Weekday::from_sunday_zero_offset`] builds a weekday from |
23 | | /// a scheme that starts the week on Sunday at offset `0`, while |
24 | | /// [`Weekday::to_sunday_zero_offset`] converts to it. |
25 | | /// * [`Weekday::from_sunday_one_offset`] builds a weekday from |
26 | | /// a scheme that starts the week on Sunday at offset `1`, while |
27 | | /// [`Weekday::to_sunday_one_offset`] converts to it. |
28 | | /// |
29 | | /// # Arithmetic |
30 | | /// |
31 | | /// This type provides [`Weekday::wrapping_add`] and [`Weekday::wrapping_sub`] |
32 | | /// for performing wrapping arithmetic on weekdays. These are also available |
33 | | /// via operator overloading: |
34 | | /// |
35 | | /// ``` |
36 | | /// use jiff::civil::Weekday; |
37 | | /// |
38 | | /// assert_eq!(Weekday::Monday + 1, Weekday::Tuesday); |
39 | | /// assert_eq!(Weekday::Sunday - 1, Weekday::Saturday); |
40 | | /// ``` |
41 | | /// |
42 | | /// # Comparisons |
43 | | /// |
44 | | /// This type provides `Eq` and `PartialEq` trait implementations for easy |
45 | | /// comparison: |
46 | | /// |
47 | | /// ``` |
48 | | /// use jiff::civil::Weekday; |
49 | | /// |
50 | | /// assert_eq!(Weekday::Wednesday, Weekday::Wednesday + 7); |
51 | | /// assert_ne!(Weekday::Thursday, Weekday::Friday); |
52 | | /// ``` |
53 | | /// |
54 | | /// But this type specifically does not provide `Ord` or `PartialOrd` trait |
55 | | /// implementations. Such an implementation would require deciding whether |
56 | | /// Sunday is less than Monday or greater than Monday. The former case |
57 | | /// corresponds to a week scheme where Sunday is the first day in the week, |
58 | | /// where as the latter corresponds to a scheme where Monday is the first day. |
59 | | /// Since both schemes are in widespread use, it would be inappropriate to bake |
60 | | /// in an assumption of one or the other. Instead, one can convert a weekday |
61 | | /// into the desired offset scheme, and then compare the offsets: |
62 | | /// |
63 | | /// ``` |
64 | | /// use jiff::civil::Weekday; |
65 | | /// |
66 | | /// let (sun, mon) = (Weekday::Sunday, Weekday::Monday); |
67 | | /// assert!(sun.to_sunday_zero_offset() < mon.to_sunday_zero_offset()); |
68 | | /// assert!(sun.to_monday_zero_offset() > mon.to_monday_zero_offset()); |
69 | | /// ``` |
70 | | /// |
71 | | /// # Example |
72 | | /// |
73 | | /// This example shows the result of converting to and from different schemes: |
74 | | /// |
75 | | /// ``` |
76 | | /// use jiff::civil::Weekday; |
77 | | /// |
78 | | /// // The different representations of Monday. |
79 | | /// assert_eq!(Weekday::Monday.to_monday_zero_offset(), 0); |
80 | | /// assert_eq!(Weekday::Monday.to_monday_one_offset(), 1); |
81 | | /// assert_eq!(Weekday::Monday.to_sunday_zero_offset(), 1); |
82 | | /// assert_eq!(Weekday::Monday.to_sunday_one_offset(), 2); |
83 | | /// |
84 | | /// // The different representations of Sunday. |
85 | | /// assert_eq!(Weekday::Sunday.to_monday_zero_offset(), 6); |
86 | | /// assert_eq!(Weekday::Sunday.to_monday_one_offset(), 7); |
87 | | /// assert_eq!(Weekday::Sunday.to_sunday_zero_offset(), 0); |
88 | | /// assert_eq!(Weekday::Sunday.to_sunday_one_offset(), 1); |
89 | | /// ``` |
90 | | #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] |
91 | | #[repr(u8)] |
92 | | #[allow(missing_docs)] |
93 | | pub enum Weekday { |
94 | | Monday = 1, |
95 | | Tuesday = 2, |
96 | | Wednesday = 3, |
97 | | Thursday = 4, |
98 | | Friday = 5, |
99 | | Saturday = 6, |
100 | | Sunday = 7, |
101 | | } |
102 | | |
103 | | impl Weekday { |
104 | | /// Convert an offset to a structured `Weekday`. |
105 | | /// |
106 | | /// The offset should be from a scheme where the first day of the week |
107 | | /// is Monday and starts numbering at `0`. |
108 | | /// |
109 | | /// # Errors |
110 | | /// |
111 | | /// This returns an error when the given offset is not in the range |
112 | | /// `0..=6`. |
113 | | /// |
114 | | /// # Example |
115 | | /// |
116 | | /// ``` |
117 | | /// use jiff::civil::Weekday; |
118 | | /// |
119 | | /// let weekday = Weekday::from_monday_zero_offset(3)?; |
120 | | /// assert_eq!(weekday, Weekday::Thursday); |
121 | | /// |
122 | | /// assert!(Weekday::from_monday_zero_offset(7).is_err()); |
123 | | /// assert!(Weekday::from_monday_zero_offset(-1).is_err()); |
124 | | /// |
125 | | /// # Ok::<(), Box<dyn std::error::Error>>(()) |
126 | | /// ``` |
127 | | #[inline] |
128 | 0 | pub fn from_monday_zero_offset(offset: i8) -> Result<Weekday, Error> { |
129 | 0 | let offset = t::WeekdayZero::try_new("weekday", offset)?; |
130 | 0 | Ok(Weekday::from_monday_zero_offset_ranged(offset)) |
131 | 0 | } |
132 | | |
133 | | /// Convert an offset to a structured `Weekday`. |
134 | | /// |
135 | | /// The offset should be from a scheme where the first day of the week |
136 | | /// is Monday and starts numbering at `1`. |
137 | | /// |
138 | | /// # Errors |
139 | | /// |
140 | | /// This returns an error when the given offset is not in the range |
141 | | /// `1..=7`. |
142 | | /// |
143 | | /// # Example |
144 | | /// |
145 | | /// ``` |
146 | | /// use jiff::civil::Weekday; |
147 | | /// |
148 | | /// let weekday = Weekday::from_monday_one_offset(4)?; |
149 | | /// assert_eq!(weekday, Weekday::Thursday); |
150 | | /// |
151 | | /// assert!(Weekday::from_monday_one_offset(8).is_err()); |
152 | | /// assert!(Weekday::from_monday_one_offset(0).is_err()); |
153 | | /// |
154 | | /// # Ok::<(), Box<dyn std::error::Error>>(()) |
155 | | /// ``` |
156 | | #[inline] |
157 | 0 | pub fn from_monday_one_offset(offset: i8) -> Result<Weekday, Error> { |
158 | 0 | let offset = t::WeekdayOne::try_new("weekday", offset)?; |
159 | 0 | Ok(Weekday::from_monday_one_offset_ranged(offset)) |
160 | 0 | } |
161 | | |
162 | | /// Convert an offset to a structured `Weekday`. |
163 | | /// |
164 | | /// The offset should be from a scheme where the first day of the week |
165 | | /// is Sunday and starts numbering at `0`. |
166 | | /// |
167 | | /// # Errors |
168 | | /// |
169 | | /// This returns an error when the given offset is not in the range |
170 | | /// `0..=6`. |
171 | | /// |
172 | | /// # Example |
173 | | /// |
174 | | /// ``` |
175 | | /// use jiff::civil::Weekday; |
176 | | /// |
177 | | /// let weekday = Weekday::from_sunday_zero_offset(4)?; |
178 | | /// assert_eq!(weekday, Weekday::Thursday); |
179 | | /// |
180 | | /// assert!(Weekday::from_sunday_zero_offset(7).is_err()); |
181 | | /// assert!(Weekday::from_sunday_zero_offset(-1).is_err()); |
182 | | /// |
183 | | /// # Ok::<(), Box<dyn std::error::Error>>(()) |
184 | | /// ``` |
185 | | #[inline] |
186 | 0 | pub fn from_sunday_zero_offset(offset: i8) -> Result<Weekday, Error> { |
187 | 0 | let offset = t::WeekdayZero::try_new("weekday", offset)?; |
188 | 0 | Ok(Weekday::from_sunday_zero_offset_ranged(offset)) |
189 | 0 | } |
190 | | |
191 | | /// Convert an offset to a structured `Weekday`. |
192 | | /// |
193 | | /// The offset should be from a scheme where the first day of the week |
194 | | /// is Sunday and starts numbering at `1`. |
195 | | /// |
196 | | /// # Errors |
197 | | /// |
198 | | /// This returns an error when the given offset is not in the range |
199 | | /// `1..=7`. |
200 | | /// |
201 | | /// # Example |
202 | | /// |
203 | | /// ``` |
204 | | /// use jiff::civil::Weekday; |
205 | | /// |
206 | | /// let weekday = Weekday::from_sunday_one_offset(5)?; |
207 | | /// assert_eq!(weekday, Weekday::Thursday); |
208 | | /// |
209 | | /// assert!(Weekday::from_sunday_one_offset(8).is_err()); |
210 | | /// assert!(Weekday::from_sunday_one_offset(0).is_err()); |
211 | | /// |
212 | | /// # Ok::<(), Box<dyn std::error::Error>>(()) |
213 | | /// ``` |
214 | | #[inline] |
215 | 0 | pub fn from_sunday_one_offset(offset: i8) -> Result<Weekday, Error> { |
216 | 0 | let offset = t::WeekdayOne::try_new("weekday", offset)?; |
217 | 0 | Ok(Weekday::from_sunday_one_offset_ranged(offset)) |
218 | 0 | } |
219 | | |
220 | | /// Returns this weekday as an offset. |
221 | | /// |
222 | | /// The offset returned is computed based on a week that starts with Monday |
223 | | /// and begins numbering at `0`. |
224 | | /// |
225 | | /// # Example |
226 | | /// |
227 | | /// ``` |
228 | | /// use jiff::civil::Weekday; |
229 | | /// |
230 | | /// assert_eq!(Weekday::Thursday.to_monday_zero_offset(), 3); |
231 | | /// |
232 | | /// # Ok::<(), Box<dyn std::error::Error>>(()) |
233 | | /// ``` |
234 | | #[inline] |
235 | 0 | pub fn to_monday_zero_offset(self) -> i8 { |
236 | 0 | self.to_monday_zero_offset_ranged().get() |
237 | 0 | } |
238 | | |
239 | | /// Returns this weekday as an offset. |
240 | | /// |
241 | | /// The offset returned is computed based on a week that starts with Monday |
242 | | /// and begins numbering at `1`. |
243 | | /// |
244 | | /// # Example |
245 | | /// |
246 | | /// ``` |
247 | | /// use jiff::civil::Weekday; |
248 | | /// |
249 | | /// assert_eq!(Weekday::Thursday.to_monday_one_offset(), 4); |
250 | | /// |
251 | | /// # Ok::<(), Box<dyn std::error::Error>>(()) |
252 | | /// ``` |
253 | | #[inline] |
254 | 0 | pub fn to_monday_one_offset(self) -> i8 { |
255 | 0 | self.to_monday_one_offset_ranged().get() |
256 | 0 | } |
257 | | |
258 | | /// Returns this weekday as an offset. |
259 | | /// |
260 | | /// The offset returned is computed based on a week that starts with Sunday |
261 | | /// and begins numbering at `0`. |
262 | | /// |
263 | | /// # Example |
264 | | /// |
265 | | /// ``` |
266 | | /// use jiff::civil::Weekday; |
267 | | /// |
268 | | /// assert_eq!(Weekday::Thursday.to_sunday_zero_offset(), 4); |
269 | | /// |
270 | | /// # Ok::<(), Box<dyn std::error::Error>>(()) |
271 | | /// ``` |
272 | | #[inline] |
273 | 0 | pub fn to_sunday_zero_offset(self) -> i8 { |
274 | 0 | self.to_sunday_zero_offset_ranged().get() |
275 | 0 | } |
276 | | |
277 | | /// Returns this weekday as an offset. |
278 | | /// |
279 | | /// The offset returned is computed based on a week that starts with Sunday |
280 | | /// and begins numbering at `1`. |
281 | | /// |
282 | | /// # Example |
283 | | /// |
284 | | /// ``` |
285 | | /// use jiff::civil::Weekday; |
286 | | /// |
287 | | /// assert_eq!(Weekday::Thursday.to_sunday_one_offset(), 5); |
288 | | /// |
289 | | /// # Ok::<(), Box<dyn std::error::Error>>(()) |
290 | | /// ``` |
291 | | #[inline] |
292 | 0 | pub fn to_sunday_one_offset(self) -> i8 { |
293 | 0 | self.to_sunday_one_offset_ranged().get() |
294 | 0 | } |
295 | | |
296 | | /// Returns the next weekday, wrapping around at the end of week to the |
297 | | /// beginning of the week. |
298 | | /// |
299 | | /// This is a convenience routing for calling [`Weekday::wrapping_add`] |
300 | | /// with a value of `1`. |
301 | | /// |
302 | | /// # Example |
303 | | /// |
304 | | /// ``` |
305 | | /// use jiff::civil::Weekday; |
306 | | /// |
307 | | /// assert_eq!(Weekday::Wednesday.next(), Weekday::Thursday); |
308 | | /// assert_eq!(Weekday::Sunday.next(), Weekday::Monday); |
309 | | /// assert_eq!(Weekday::Saturday.next(), Weekday::Sunday); |
310 | | /// ``` |
311 | | #[inline] |
312 | 0 | pub fn next(self) -> Weekday { |
313 | 0 | self.wrapping_add(1) |
314 | 0 | } |
315 | | |
316 | | /// Returns the previous weekday, wrapping around at the beginning of week |
317 | | /// to the end of the week. |
318 | | /// |
319 | | /// This is a convenience routing for calling [`Weekday::wrapping_sub`] |
320 | | /// with a value of `1`. |
321 | | /// |
322 | | /// # Example |
323 | | /// |
324 | | /// ``` |
325 | | /// use jiff::civil::Weekday; |
326 | | /// |
327 | | /// assert_eq!(Weekday::Wednesday.previous(), Weekday::Tuesday); |
328 | | /// assert_eq!(Weekday::Sunday.previous(), Weekday::Saturday); |
329 | | /// assert_eq!(Weekday::Saturday.previous(), Weekday::Friday); |
330 | | /// ``` |
331 | | #[inline] |
332 | 0 | pub fn previous(self) -> Weekday { |
333 | 0 | self.wrapping_sub(1) |
334 | 0 | } |
335 | | |
336 | | /// Returns the number of days from `other` to this weekday. |
337 | | /// |
338 | | /// Adding the returned number of days to `other` is guaranteed to sum to |
339 | | /// this weekday. The number of days returned is guaranteed to be in the |
340 | | /// range `0..=6`. |
341 | | /// |
342 | | /// # Example |
343 | | /// |
344 | | /// ``` |
345 | | /// use jiff::civil::Weekday; |
346 | | /// |
347 | | /// assert_eq!(Weekday::Friday.since(Weekday::Tuesday), 3); |
348 | | /// assert_eq!(Weekday::Tuesday.since(Weekday::Tuesday), 0); |
349 | | /// assert_eq!(Weekday::Monday.since(Weekday::Sunday), 1); |
350 | | /// assert_eq!(Weekday::Sunday.since(Weekday::Monday), 6); |
351 | | /// ``` |
352 | | #[inline] |
353 | 0 | pub fn since(self, other: Weekday) -> i8 { |
354 | 0 | self.since_ranged(other).get() |
355 | 0 | } |
356 | | |
357 | | /// Returns the number of days until `other` from this weekday. |
358 | | /// |
359 | | /// Adding the returned number of days to this weekday is guaranteed to sum |
360 | | /// to `other` weekday. The number of days returned is guaranteed to be in |
361 | | /// the range `0..=6`. |
362 | | /// |
363 | | /// # Example |
364 | | /// |
365 | | /// ``` |
366 | | /// use jiff::civil::Weekday; |
367 | | /// |
368 | | /// assert_eq!(Weekday::Friday.until(Weekday::Tuesday), 4); |
369 | | /// assert_eq!(Weekday::Tuesday.until(Weekday::Tuesday), 0); |
370 | | /// assert_eq!(Weekday::Monday.until(Weekday::Sunday), 6); |
371 | | /// assert_eq!(Weekday::Sunday.until(Weekday::Monday), 1); |
372 | | /// ``` |
373 | | #[inline] |
374 | 0 | pub fn until(self, other: Weekday) -> i8 { |
375 | 0 | self.until_ranged(other).get() |
376 | 0 | } |
377 | | |
378 | | /// Add the given number of days to this weekday, using wrapping arithmetic, |
379 | | /// and return the resulting weekday. |
380 | | /// |
381 | | /// Adding a multiple of `7` (including `0`) is guaranteed to produce the |
382 | | /// same weekday as this one. |
383 | | /// |
384 | | /// Note that this routine is also available via the `+` operator. |
385 | | /// |
386 | | /// # Example |
387 | | /// |
388 | | /// ``` |
389 | | /// use jiff::civil::Weekday; |
390 | | /// |
391 | | /// assert_eq!(Weekday::Sunday.wrapping_add(1), Weekday::Monday); |
392 | | /// assert_eq!(Weekday::Sunday.wrapping_add(2), Weekday::Tuesday); |
393 | | /// assert_eq!(Weekday::Saturday.wrapping_add(1), Weekday::Sunday); |
394 | | /// assert_eq!(Weekday::Saturday.wrapping_add(7), Weekday::Saturday); |
395 | | /// assert_eq!(Weekday::Sunday.wrapping_add(-1), Weekday::Saturday); |
396 | | /// ``` |
397 | | /// |
398 | | /// Wrapping arithmetic is also performed by the `+` operator: |
399 | | /// |
400 | | /// ``` |
401 | | /// use jiff::civil::Weekday; |
402 | | /// |
403 | | /// assert_eq!(Weekday::Sunday + 1, Weekday::Monday); |
404 | | /// assert_eq!(Weekday::Sunday + 2, Weekday::Tuesday); |
405 | | /// assert_eq!(Weekday::Saturday + 1, Weekday::Sunday); |
406 | | /// assert_eq!(Weekday::Saturday + 7, Weekday::Saturday); |
407 | | /// assert_eq!(Weekday::Sunday + -1, Weekday::Saturday); |
408 | | /// // The weekday can also be on the right hand side of addition: |
409 | | /// assert_eq!(1 + Weekday::Sunday, Weekday::Monday); |
410 | | /// ``` |
411 | | #[inline] |
412 | 0 | pub fn wrapping_add<D: Into<i64>>(self, days: D) -> Weekday { |
413 | 0 | let start = t::NoUnits::rfrom(self.to_monday_zero_offset_ranged()); |
414 | 0 | // OK because all i64 values fit in a NoUnits. |
415 | 0 | let rhs = t::NoUnits::new(days.into()).unwrap(); |
416 | 0 | let end = start.wrapping_add(rhs) % C(7); |
417 | 0 | Weekday::from_monday_zero_offset_ranged(end) |
418 | 0 | } |
419 | | |
420 | | /// Subtract the given number of days from this weekday, using wrapping |
421 | | /// arithmetic, and return the resulting weekday. |
422 | | /// |
423 | | /// Subtracting a multiple of `7` (including `0`) is guaranteed to produce |
424 | | /// the same weekday as this one. |
425 | | /// |
426 | | /// Note that this routine is also available via the `-` operator. |
427 | | /// |
428 | | /// # Example |
429 | | /// |
430 | | /// ``` |
431 | | /// use jiff::civil::Weekday; |
432 | | /// |
433 | | /// assert_eq!(Weekday::Sunday.wrapping_sub(1), Weekday::Saturday); |
434 | | /// assert_eq!(Weekday::Sunday.wrapping_sub(2), Weekday::Friday); |
435 | | /// assert_eq!(Weekday::Saturday.wrapping_sub(1), Weekday::Friday); |
436 | | /// assert_eq!(Weekday::Saturday.wrapping_sub(7), Weekday::Saturday); |
437 | | /// assert_eq!(Weekday::Sunday.wrapping_sub(-1), Weekday::Monday); |
438 | | /// ``` |
439 | | /// |
440 | | /// Wrapping arithmetic is also performed by the `-` operator: |
441 | | /// |
442 | | /// ``` |
443 | | /// use jiff::civil::Weekday; |
444 | | /// |
445 | | /// assert_eq!(Weekday::Sunday - 1, Weekday::Saturday); |
446 | | /// assert_eq!(Weekday::Sunday - 2, Weekday::Friday); |
447 | | /// assert_eq!(Weekday::Saturday - 1, Weekday::Friday); |
448 | | /// assert_eq!(Weekday::Saturday - 7, Weekday::Saturday); |
449 | | /// assert_eq!(Weekday::Sunday - -1, Weekday::Monday); |
450 | | /// ``` |
451 | | /// |
452 | | /// Unlike addition, since subtraction is not commutative and negating a |
453 | | /// weekday has no semantic meaning, the weekday cannot be on the right |
454 | | /// hand side of the `-` operator. |
455 | | #[inline] |
456 | 0 | pub fn wrapping_sub<D: Into<i64>>(self, days: D) -> Weekday { |
457 | 0 | self.wrapping_add(-days.into()) |
458 | 0 | } |
459 | | |
460 | | /// Starting with this weekday, this returns an unending iterator that |
461 | | /// cycles forward through the days of the week. |
462 | | /// |
463 | | /// # Example |
464 | | /// |
465 | | /// ``` |
466 | | /// use jiff::civil::Weekday; |
467 | | /// |
468 | | /// let mut it = Weekday::Tuesday.cycle_forward(); |
469 | | /// assert_eq!(it.next(), Some(Weekday::Tuesday)); |
470 | | /// assert_eq!(it.next(), Some(Weekday::Wednesday)); |
471 | | /// assert_eq!(it.next(), Some(Weekday::Thursday)); |
472 | | /// assert_eq!(it.next(), Some(Weekday::Friday)); |
473 | | /// assert_eq!(it.next(), Some(Weekday::Saturday)); |
474 | | /// assert_eq!(it.next(), Some(Weekday::Sunday)); |
475 | | /// assert_eq!(it.next(), Some(Weekday::Monday)); |
476 | | /// assert_eq!(it.next(), Some(Weekday::Tuesday)); |
477 | | /// ``` |
478 | | #[inline] |
479 | 0 | pub fn cycle_forward(self) -> WeekdaysForward { |
480 | 0 | let nexts = [ |
481 | 0 | self, |
482 | 0 | self.wrapping_add(1), |
483 | 0 | self.wrapping_add(2), |
484 | 0 | self.wrapping_add(3), |
485 | 0 | self.wrapping_add(4), |
486 | 0 | self.wrapping_add(5), |
487 | 0 | self.wrapping_add(6), |
488 | 0 | ]; |
489 | 0 | WeekdaysForward { it: nexts.into_iter().cycle() } |
490 | 0 | } |
491 | | |
492 | | /// Starting with this weekday, this returns an unending iterator that |
493 | | /// cycles backward through the days of the week. |
494 | | /// |
495 | | /// # Example |
496 | | /// |
497 | | /// ``` |
498 | | /// use jiff::civil::Weekday; |
499 | | /// |
500 | | /// let mut it = Weekday::Tuesday.cycle_reverse(); |
501 | | /// assert_eq!(it.next(), Some(Weekday::Tuesday)); |
502 | | /// assert_eq!(it.next(), Some(Weekday::Monday)); |
503 | | /// assert_eq!(it.next(), Some(Weekday::Sunday)); |
504 | | /// assert_eq!(it.next(), Some(Weekday::Saturday)); |
505 | | /// assert_eq!(it.next(), Some(Weekday::Friday)); |
506 | | /// assert_eq!(it.next(), Some(Weekday::Thursday)); |
507 | | /// assert_eq!(it.next(), Some(Weekday::Wednesday)); |
508 | | /// assert_eq!(it.next(), Some(Weekday::Tuesday)); |
509 | | /// ``` |
510 | | #[inline] |
511 | 0 | pub fn cycle_reverse(self) -> WeekdaysReverse { |
512 | 0 | let nexts = [ |
513 | 0 | self, |
514 | 0 | self.wrapping_sub(1), |
515 | 0 | self.wrapping_sub(2), |
516 | 0 | self.wrapping_sub(3), |
517 | 0 | self.wrapping_sub(4), |
518 | 0 | self.wrapping_sub(5), |
519 | 0 | self.wrapping_sub(6), |
520 | 0 | ]; |
521 | 0 | WeekdaysReverse { it: nexts.into_iter().cycle() } |
522 | 0 | } |
523 | | } |
524 | | |
525 | | impl Weekday { |
526 | | #[inline] |
527 | 0 | pub(crate) fn from_monday_zero_offset_ranged( |
528 | 0 | offset: impl RInto<t::WeekdayZero>, |
529 | 0 | ) -> Weekday { |
530 | 0 | match offset.rinto().get() { |
531 | 0 | 0 => Weekday::Monday, |
532 | 0 | 1 => Weekday::Tuesday, |
533 | 0 | 2 => Weekday::Wednesday, |
534 | 0 | 3 => Weekday::Thursday, |
535 | 0 | 4 => Weekday::Friday, |
536 | 0 | 5 => Weekday::Saturday, |
537 | 0 | 6 => Weekday::Sunday, |
538 | 0 | _ => unreachable!(), |
539 | | } |
540 | 0 | } Unexecuted instantiation: <jiff::civil::weekday::Weekday>::from_monday_zero_offset_ranged::<jiff::util::rangeint::ri8<0, 6>> Unexecuted instantiation: <jiff::civil::weekday::Weekday>::from_monday_zero_offset_ranged::<jiff::util::rangeint::ri8<1, 7>> |
541 | | |
542 | | #[inline] |
543 | 0 | pub(crate) fn from_monday_one_offset_ranged( |
544 | 0 | offset: impl RInto<t::WeekdayOne>, |
545 | 0 | ) -> Weekday { |
546 | 0 | let offset_zero = offset.rinto() - C(1); |
547 | 0 | Weekday::from_monday_zero_offset_ranged(offset_zero) |
548 | 0 | } |
549 | | |
550 | | #[inline] |
551 | 0 | pub(crate) fn from_sunday_zero_offset_ranged( |
552 | 0 | offset: impl RInto<t::WeekdayZero>, |
553 | 0 | ) -> Weekday { |
554 | 0 | let offset_sunday = (offset.rinto() - C(1)) % C(7); |
555 | 0 | Weekday::from_monday_zero_offset_ranged(offset_sunday) |
556 | 0 | } |
557 | | |
558 | | #[inline] |
559 | 0 | pub(crate) fn from_sunday_one_offset_ranged( |
560 | 0 | offset: impl RInto<t::WeekdayOne>, |
561 | 0 | ) -> Weekday { |
562 | 0 | let offset_zero = offset.rinto() - C(1); |
563 | 0 | Weekday::from_sunday_zero_offset_ranged(offset_zero) |
564 | 0 | } |
565 | | |
566 | | #[inline] |
567 | 0 | pub(crate) fn from_iweekday(iweekday: IWeekday) -> Weekday { |
568 | 0 | match iweekday.to_monday_one_offset() { |
569 | 0 | 1 => Weekday::Monday, |
570 | 0 | 2 => Weekday::Tuesday, |
571 | 0 | 3 => Weekday::Wednesday, |
572 | 0 | 4 => Weekday::Thursday, |
573 | 0 | 5 => Weekday::Friday, |
574 | 0 | 6 => Weekday::Saturday, |
575 | 0 | 7 => Weekday::Sunday, |
576 | 0 | _ => unreachable!(), |
577 | | } |
578 | 0 | } |
579 | | |
580 | | #[inline] |
581 | 0 | pub(crate) fn to_monday_zero_offset_ranged(self) -> t::WeekdayZero { |
582 | 0 | (self.to_monday_one_offset_ranged() - C(1)).rinto() |
583 | 0 | } |
584 | | |
585 | | #[inline] |
586 | 0 | pub(crate) fn to_monday_one_offset_ranged(self) -> t::WeekdayOne { |
587 | 0 | t::WeekdayOne::new_unchecked(self as i8) |
588 | 0 | } |
589 | | |
590 | | #[inline] |
591 | 0 | pub(crate) fn to_sunday_zero_offset_ranged(self) -> t::WeekdayZero { |
592 | 0 | (self.to_monday_zero_offset_ranged() + C(1)) % C(7) |
593 | 0 | } |
594 | | |
595 | | #[inline] |
596 | 0 | pub(crate) fn to_sunday_one_offset_ranged(self) -> t::WeekdayOne { |
597 | 0 | (self.to_sunday_zero_offset_ranged() + C(1)).rinto() |
598 | 0 | } |
599 | | |
600 | | #[inline] |
601 | 0 | pub(crate) fn to_iweekday(self) -> IWeekday { |
602 | 0 | IWeekday::from_monday_one_offset(self.to_monday_one_offset()) |
603 | 0 | } |
604 | | |
605 | | #[inline] |
606 | 0 | pub(crate) fn since_ranged(self, other: Weekday) -> t::WeekdayZero { |
607 | 0 | (self.to_monday_zero_offset_ranged() |
608 | 0 | - other.to_monday_zero_offset_ranged()) |
609 | 0 | % C(7) |
610 | 0 | } |
611 | | |
612 | | #[inline] |
613 | 0 | pub(crate) fn until_ranged(self, other: Weekday) -> t::WeekdayZero { |
614 | 0 | other.since_ranged(self) |
615 | 0 | } |
616 | | } |
617 | | |
618 | | impl core::ops::Add<i8> for Weekday { |
619 | | type Output = Weekday; |
620 | | |
621 | | #[inline] |
622 | 0 | fn add(self, rhs: i8) -> Weekday { |
623 | 0 | self.wrapping_add(rhs) |
624 | 0 | } |
625 | | } |
626 | | |
627 | | impl core::ops::Add<i16> for Weekday { |
628 | | type Output = Weekday; |
629 | | |
630 | | #[inline] |
631 | 0 | fn add(self, rhs: i16) -> Weekday { |
632 | 0 | self.wrapping_add(rhs) |
633 | 0 | } |
634 | | } |
635 | | |
636 | | impl core::ops::Add<i32> for Weekday { |
637 | | type Output = Weekday; |
638 | | |
639 | | #[inline] |
640 | 0 | fn add(self, rhs: i32) -> Weekday { |
641 | 0 | self.wrapping_add(rhs) |
642 | 0 | } |
643 | | } |
644 | | |
645 | | impl core::ops::Add<i64> for Weekday { |
646 | | type Output = Weekday; |
647 | | |
648 | | #[inline] |
649 | 0 | fn add(self, rhs: i64) -> Weekday { |
650 | 0 | self.wrapping_add(rhs) |
651 | 0 | } |
652 | | } |
653 | | |
654 | | // Since addition is commutative, we don't might if users write `n + weekday` |
655 | | // or `weekday + n`. |
656 | | |
657 | | impl core::ops::Add<Weekday> for i8 { |
658 | | type Output = Weekday; |
659 | | |
660 | | #[inline] |
661 | 0 | fn add(self, rhs: Weekday) -> Weekday { |
662 | 0 | rhs.wrapping_add(self) |
663 | 0 | } |
664 | | } |
665 | | |
666 | | impl core::ops::Add<Weekday> for i16 { |
667 | | type Output = Weekday; |
668 | | |
669 | | #[inline] |
670 | 0 | fn add(self, rhs: Weekday) -> Weekday { |
671 | 0 | rhs.wrapping_add(self) |
672 | 0 | } |
673 | | } |
674 | | |
675 | | impl core::ops::Add<Weekday> for i32 { |
676 | | type Output = Weekday; |
677 | | |
678 | | #[inline] |
679 | 0 | fn add(self, rhs: Weekday) -> Weekday { |
680 | 0 | rhs.wrapping_add(self) |
681 | 0 | } |
682 | | } |
683 | | |
684 | | impl core::ops::Add<Weekday> for i64 { |
685 | | type Output = Weekday; |
686 | | |
687 | | #[inline] |
688 | 0 | fn add(self, rhs: Weekday) -> Weekday { |
689 | 0 | rhs.wrapping_add(self) |
690 | 0 | } |
691 | | } |
692 | | |
693 | | impl core::ops::AddAssign<i8> for Weekday { |
694 | | #[inline] |
695 | 0 | fn add_assign(&mut self, rhs: i8) { |
696 | 0 | *self = *self + rhs; |
697 | 0 | } |
698 | | } |
699 | | |
700 | | impl core::ops::AddAssign<i16> for Weekday { |
701 | | #[inline] |
702 | 0 | fn add_assign(&mut self, rhs: i16) { |
703 | 0 | *self = *self + rhs; |
704 | 0 | } |
705 | | } |
706 | | |
707 | | impl core::ops::AddAssign<i32> for Weekday { |
708 | | #[inline] |
709 | 0 | fn add_assign(&mut self, rhs: i32) { |
710 | 0 | *self = *self + rhs; |
711 | 0 | } |
712 | | } |
713 | | |
714 | | impl core::ops::AddAssign<i64> for Weekday { |
715 | | #[inline] |
716 | 0 | fn add_assign(&mut self, rhs: i64) { |
717 | 0 | *self = *self + rhs; |
718 | 0 | } |
719 | | } |
720 | | |
721 | | // Subtraction isn't commutative, so we only define it when the right hand |
722 | | // side is an integer. Otherwise we'd need a concept of what it means to |
723 | | // "negate" a weekday, which doesn't really make sense? |
724 | | |
725 | | impl core::ops::Sub<i8> for Weekday { |
726 | | type Output = Weekday; |
727 | | |
728 | | #[inline] |
729 | 0 | fn sub(self, rhs: i8) -> Weekday { |
730 | 0 | self.wrapping_sub(rhs) |
731 | 0 | } |
732 | | } |
733 | | |
734 | | impl core::ops::Sub<i16> for Weekday { |
735 | | type Output = Weekday; |
736 | | |
737 | | #[inline] |
738 | 0 | fn sub(self, rhs: i16) -> Weekday { |
739 | 0 | self.wrapping_sub(rhs) |
740 | 0 | } |
741 | | } |
742 | | |
743 | | impl core::ops::Sub<i32> for Weekday { |
744 | | type Output = Weekday; |
745 | | |
746 | | #[inline] |
747 | 0 | fn sub(self, rhs: i32) -> Weekday { |
748 | 0 | self.wrapping_sub(rhs) |
749 | 0 | } |
750 | | } |
751 | | |
752 | | impl core::ops::Sub<i64> for Weekday { |
753 | | type Output = Weekday; |
754 | | |
755 | | #[inline] |
756 | 0 | fn sub(self, rhs: i64) -> Weekday { |
757 | 0 | self.wrapping_sub(rhs) |
758 | 0 | } |
759 | | } |
760 | | |
761 | | impl core::ops::SubAssign<i8> for Weekday { |
762 | | #[inline] |
763 | 0 | fn sub_assign(&mut self, rhs: i8) { |
764 | 0 | *self = *self - rhs; |
765 | 0 | } |
766 | | } |
767 | | |
768 | | impl core::ops::SubAssign<i16> for Weekday { |
769 | | #[inline] |
770 | 0 | fn sub_assign(&mut self, rhs: i16) { |
771 | 0 | *self = *self - rhs; |
772 | 0 | } |
773 | | } |
774 | | |
775 | | impl core::ops::SubAssign<i32> for Weekday { |
776 | | #[inline] |
777 | 0 | fn sub_assign(&mut self, rhs: i32) { |
778 | 0 | *self = *self - rhs; |
779 | 0 | } |
780 | | } |
781 | | |
782 | | impl core::ops::SubAssign<i64> for Weekday { |
783 | | #[inline] |
784 | 0 | fn sub_assign(&mut self, rhs: i64) { |
785 | 0 | *self = *self - rhs; |
786 | 0 | } |
787 | | } |
788 | | |
789 | | #[cfg(test)] |
790 | | impl quickcheck::Arbitrary for Weekday { |
791 | | fn arbitrary(g: &mut quickcheck::Gen) -> Weekday { |
792 | | let offset = t::WeekdayZero::arbitrary(g); |
793 | | Weekday::from_monday_zero_offset_ranged(offset) |
794 | | } |
795 | | |
796 | | fn shrink(&self) -> alloc::boxed::Box<dyn Iterator<Item = Weekday>> { |
797 | | alloc::boxed::Box::new( |
798 | | self.to_monday_zero_offset_ranged() |
799 | | .shrink() |
800 | | .map(Weekday::from_monday_zero_offset_ranged), |
801 | | ) |
802 | | } |
803 | | } |
804 | | |
805 | | /// An unending iterator of the days of the week. |
806 | | /// |
807 | | /// This iterator is created by calling [`Weekday::cycle_forward`]. |
808 | | #[derive(Clone, Debug)] |
809 | | pub struct WeekdaysForward { |
810 | | it: core::iter::Cycle<core::array::IntoIter<Weekday, 7>>, |
811 | | } |
812 | | |
813 | | impl Iterator for WeekdaysForward { |
814 | | type Item = Weekday; |
815 | | |
816 | | #[inline] |
817 | 0 | fn next(&mut self) -> Option<Weekday> { |
818 | 0 | self.it.next() |
819 | 0 | } |
820 | | } |
821 | | |
822 | | impl core::iter::FusedIterator for WeekdaysForward {} |
823 | | |
824 | | /// An unending iterator of the days of the week in reverse. |
825 | | /// |
826 | | /// This iterator is created by calling [`Weekday::cycle_reverse`]. |
827 | | #[derive(Clone, Debug)] |
828 | | pub struct WeekdaysReverse { |
829 | | it: core::iter::Cycle<core::array::IntoIter<Weekday, 7>>, |
830 | | } |
831 | | |
832 | | impl Iterator for WeekdaysReverse { |
833 | | type Item = Weekday; |
834 | | |
835 | | #[inline] |
836 | 0 | fn next(&mut self) -> Option<Weekday> { |
837 | 0 | self.it.next() |
838 | 0 | } |
839 | | } |
840 | | |
841 | | impl core::iter::FusedIterator for WeekdaysReverse {} |
842 | | |
843 | | #[cfg(test)] |
844 | | mod tests { |
845 | | use super::*; |
846 | | |
847 | | quickcheck::quickcheck! { |
848 | | fn prop_since_add_equals_self(wd1: Weekday, wd2: Weekday) -> bool { |
849 | | let days = wd1.since(wd2); |
850 | | wd2.wrapping_add(days) == wd1 |
851 | | } |
852 | | |
853 | | fn prop_until_add_equals_other(wd1: Weekday, wd2: Weekday) -> bool { |
854 | | let days = wd1.until(wd2); |
855 | | wd1.wrapping_add(days) == wd2 |
856 | | } |
857 | | } |
858 | | } |