Coverage Report

Created: 2025-07-23 06:05

/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
}