time/
weekday.rs

1//! Days of the week.
2
3use core::fmt;
4use core::str::FromStr;
5
6use powerfmt::smart_display::{FormatterOptions, Metadata, SmartDisplay};
7
8use self::Weekday::*;
9use crate::error;
10
11/// Days of the week.
12///
13/// As order is dependent on context (Sunday could be either two days after or five days before
14/// Friday), this type does not implement `PartialOrd` or `Ord`.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub enum Weekday {
17    #[expect(missing_docs)]
18    Monday,
19    #[expect(missing_docs)]
20    Tuesday,
21    #[expect(missing_docs)]
22    Wednesday,
23    #[expect(missing_docs)]
24    Thursday,
25    #[expect(missing_docs)]
26    Friday,
27    #[expect(missing_docs)]
28    Saturday,
29    #[expect(missing_docs)]
30    Sunday,
31}
32
33impl Weekday {
34    /// Get the previous weekday.
35    ///
36    /// ```rust
37    /// # use time::Weekday;
38    /// assert_eq!(Weekday::Tuesday.previous(), Weekday::Monday);
39    /// ```
40    #[inline]
41    pub const fn previous(self) -> Self {
42        match self {
43            Monday => Sunday,
44            Tuesday => Monday,
45            Wednesday => Tuesday,
46            Thursday => Wednesday,
47            Friday => Thursday,
48            Saturday => Friday,
49            Sunday => Saturday,
50        }
51    }
52
53    /// Get the next weekday.
54    ///
55    /// ```rust
56    /// # use time::Weekday;
57    /// assert_eq!(Weekday::Monday.next(), Weekday::Tuesday);
58    /// ```
59    #[inline]
60    pub const fn next(self) -> Self {
61        match self {
62            Monday => Tuesday,
63            Tuesday => Wednesday,
64            Wednesday => Thursday,
65            Thursday => Friday,
66            Friday => Saturday,
67            Saturday => Sunday,
68            Sunday => Monday,
69        }
70    }
71
72    /// Get n-th next day.
73    ///
74    /// ```rust
75    /// # use time::Weekday;
76    /// assert_eq!(Weekday::Monday.nth_next(1), Weekday::Tuesday);
77    /// assert_eq!(Weekday::Sunday.nth_next(10), Weekday::Wednesday);
78    /// ```
79    #[inline]
80    pub const fn nth_next(self, n: u8) -> Self {
81        match (self.number_days_from_monday() + n % 7) % 7 {
82            0 => Monday,
83            1 => Tuesday,
84            2 => Wednesday,
85            3 => Thursday,
86            4 => Friday,
87            5 => Saturday,
88            val => {
89                debug_assert!(val == 6);
90                Sunday
91            }
92        }
93    }
94
95    /// Get n-th previous day.
96    ///
97    /// ```rust
98    /// # use time::Weekday;
99    /// assert_eq!(Weekday::Monday.nth_prev(1), Weekday::Sunday);
100    /// assert_eq!(Weekday::Sunday.nth_prev(10), Weekday::Thursday);
101    /// ```
102    #[inline]
103    pub const fn nth_prev(self, n: u8) -> Self {
104        match self.number_days_from_monday().cast_signed() - (n % 7).cast_signed() {
105            1 | -6 => Tuesday,
106            2 | -5 => Wednesday,
107            3 | -4 => Thursday,
108            4 | -3 => Friday,
109            5 | -2 => Saturday,
110            6 | -1 => Sunday,
111            val => {
112                debug_assert!(val == 0);
113                Monday
114            }
115        }
116    }
117
118    /// Get the one-indexed number of days from Monday.
119    ///
120    /// ```rust
121    /// # use time::Weekday;
122    /// assert_eq!(Weekday::Monday.number_from_monday(), 1);
123    /// ```
124    #[doc(alias = "iso_weekday_number")]
125    #[inline]
126    pub const fn number_from_monday(self) -> u8 {
127        self.number_days_from_monday() + 1
128    }
129
130    /// Get the one-indexed number of days from Sunday.
131    ///
132    /// ```rust
133    /// # use time::Weekday;
134    /// assert_eq!(Weekday::Monday.number_from_sunday(), 2);
135    /// ```
136    #[inline]
137    pub const fn number_from_sunday(self) -> u8 {
138        self.number_days_from_sunday() + 1
139    }
140
141    /// Get the zero-indexed number of days from Monday.
142    ///
143    /// ```rust
144    /// # use time::Weekday;
145    /// assert_eq!(Weekday::Monday.number_days_from_monday(), 0);
146    /// ```
147    #[inline]
148    pub const fn number_days_from_monday(self) -> u8 {
149        self as u8
150    }
151
152    /// Get the zero-indexed number of days from Sunday.
153    ///
154    /// ```rust
155    /// # use time::Weekday;
156    /// assert_eq!(Weekday::Monday.number_days_from_sunday(), 1);
157    /// ```
158    #[inline]
159    pub const fn number_days_from_sunday(self) -> u8 {
160        match self {
161            Monday => 1,
162            Tuesday => 2,
163            Wednesday => 3,
164            Thursday => 4,
165            Friday => 5,
166            Saturday => 6,
167            Sunday => 0,
168        }
169    }
170}
171
172mod private {
173    /// Metadata for `Weekday`.
174    #[non_exhaustive]
175    #[derive(Debug, Clone, Copy)]
176    pub struct WeekdayMetadata;
177}
178use private::WeekdayMetadata;
179
180impl SmartDisplay for Weekday {
181    type Metadata = WeekdayMetadata;
182
183    #[inline]
184    fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
185        match self {
186            Monday => Metadata::new(6, self, WeekdayMetadata),
187            Tuesday => Metadata::new(7, self, WeekdayMetadata),
188            Wednesday => Metadata::new(9, self, WeekdayMetadata),
189            Thursday => Metadata::new(8, self, WeekdayMetadata),
190            Friday => Metadata::new(6, self, WeekdayMetadata),
191            Saturday => Metadata::new(8, self, WeekdayMetadata),
192            Sunday => Metadata::new(6, self, WeekdayMetadata),
193        }
194    }
195
196    #[inline]
197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198        f.pad(match self {
199            Monday => "Monday",
200            Tuesday => "Tuesday",
201            Wednesday => "Wednesday",
202            Thursday => "Thursday",
203            Friday => "Friday",
204            Saturday => "Saturday",
205            Sunday => "Sunday",
206        })
207    }
208}
209
210impl fmt::Display for Weekday {
211    #[inline]
212    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213        SmartDisplay::fmt(self, f)
214    }
215}
216
217impl FromStr for Weekday {
218    type Err = error::InvalidVariant;
219
220    #[inline]
221    fn from_str(s: &str) -> Result<Self, Self::Err> {
222        match s {
223            "Monday" => Ok(Monday),
224            "Tuesday" => Ok(Tuesday),
225            "Wednesday" => Ok(Wednesday),
226            "Thursday" => Ok(Thursday),
227            "Friday" => Ok(Friday),
228            "Saturday" => Ok(Saturday),
229            "Sunday" => Ok(Sunday),
230            _ => Err(error::InvalidVariant),
231        }
232    }
233}