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