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