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() as i8 - (n % 7) as i8 {
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    #[non_exhaustive]
174    #[derive(Debug, Clone, Copy)]
175    pub struct WeekdayMetadata;
176}
177use private::WeekdayMetadata;
178
179impl SmartDisplay for Weekday {
180    type Metadata = WeekdayMetadata;
181
182    #[inline]
183    fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> {
184        match self {
185            Monday => Metadata::new(6, self, WeekdayMetadata),
186            Tuesday => Metadata::new(7, self, WeekdayMetadata),
187            Wednesday => Metadata::new(9, self, WeekdayMetadata),
188            Thursday => Metadata::new(8, self, WeekdayMetadata),
189            Friday => Metadata::new(6, self, WeekdayMetadata),
190            Saturday => Metadata::new(8, self, WeekdayMetadata),
191            Sunday => Metadata::new(6, self, WeekdayMetadata),
192        }
193    }
194
195    #[inline]
196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197        f.pad(match self {
198            Monday => "Monday",
199            Tuesday => "Tuesday",
200            Wednesday => "Wednesday",
201            Thursday => "Thursday",
202            Friday => "Friday",
203            Saturday => "Saturday",
204            Sunday => "Sunday",
205        })
206    }
207}
208
209impl fmt::Display for Weekday {
210    #[inline]
211    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212        SmartDisplay::fmt(self, f)
213    }
214}
215
216impl FromStr for Weekday {
217    type Err = error::InvalidVariant;
218
219    #[inline]
220    fn from_str(s: &str) -> Result<Self, Self::Err> {
221        match s {
222            "Monday" => Ok(Monday),
223            "Tuesday" => Ok(Tuesday),
224            "Wednesday" => Ok(Wednesday),
225            "Thursday" => Ok(Thursday),
226            "Friday" => Ok(Friday),
227            "Saturday" => Ok(Saturday),
228            "Sunday" => Ok(Sunday),
229            _ => Err(error::InvalidVariant),
230        }
231    }
232}