embedded_date_time/
weekday.rs1use core::fmt;
2
3#[derive(PartialEq, Eq, Hash, Copy, Clone)]
10#[repr(u8)]
11pub enum Weekday {
12 Mon = Self::MON_NUM,
14 Tue = Self::TUE_NUM,
16 Wed = Self::WED_NUM,
18 Thu = Self::THU_NUM,
20 Fri = Self::FRI_NUM,
22 Sat = Self::SAT_NUM,
24 Sun = Self::SUN_NUM,
26}
27
28impl Weekday {
29 pub const MON_NUM: u8 = 1;
31 pub const TUE_NUM: u8 = 2;
33 pub const WED_NUM: u8 = 3;
35 pub const THU_NUM: u8 = 4;
37 pub const FRI_NUM: u8 = 5;
39 pub const SAT_NUM: u8 = 6;
41 pub const SUN_NUM: u8 = 7;
43
44 pub const MON: &str = "Mon";
46 pub const TUE: &str = "Tue";
48 pub const WED: &str = "Wed";
50 pub const THU: &str = "Thu";
52 pub const FRI: &str = "Fri";
54 pub const SAT: &str = "Sat";
56 pub const SUN: &str = "Sun";
58
59 #[must_use]
61 pub fn num_days_from_monday(self) -> u8 {
62 self as u8 - 1
63 }
64
65 #[must_use]
67 pub fn number_from_monday(self) -> u8 {
68 self as u8
69 }
70
71 #[must_use]
73 pub fn num_days_from_sunday(self) -> u8 {
74 if self == Self::Sun { 0 } else { self as u8 }
76 }
77
78 #[must_use]
80 pub fn number_from_sunday(self) -> u8 {
81 if self == Self::Sun { 1 } else { self as u8 + 1 }
83 }
84
85 #[must_use]
89 pub fn as_str(self) -> &'static str {
90 match self {
91 Self::Mon => Self::MON,
92 Self::Tue => Self::TUE,
93 Self::Wed => Self::WED,
94 Self::Thu => Self::THU,
95 Self::Fri => Self::FRI,
96 Self::Sat => Self::SAT,
97 Self::Sun => Self::SUN,
98 }
99 }
100}
101
102impl From<u8> for Weekday {
103 fn from(value: u8) -> Self {
104 match value {
107 Self::MON_NUM => Self::Mon,
108 Self::TUE_NUM => Self::Tue,
109 Self::WED_NUM => Self::Wed,
110 Self::THU_NUM => Self::Thu,
111 Self::FRI_NUM => Self::Fri,
112 Self::SAT_NUM => Self::Sat,
113 _ => Self::Sun,
114 }
115 }
116}
117
118impl AsRef<str> for Weekday {
119 fn as_ref(&self) -> &str {
120 self.as_str()
121 }
122}
123
124impl fmt::Debug for Weekday {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 fmt::Display::fmt(&self, f)
127 }
128}
129
130impl fmt::Display for Weekday {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 f.write_str(self.as_str())
133 }
134}
135
136#[cfg(feature = "defmt")]
137impl defmt::Format for Weekday {
138 fn format(&self, fmt: defmt::Formatter<'_>) {
139 defmt::write!(fmt, "{}", self.as_str());
140 }
141}
142
143#[cfg(feature = "ufmt")]
144impl ufmt::uDebug for Weekday {
145 fn fmt<W>(&self, fmt: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
146 where
147 W: ufmt::uWrite + ?Sized,
148 {
149 ufmt::uDisplay::fmt(&self, fmt)
150 }
151}
152
153#[cfg(feature = "ufmt")]
154impl ufmt::uDisplay for Weekday {
155 fn fmt<W>(&self, fmt: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
156 where
157 W: ufmt::uWrite + ?Sized,
158 {
159 fmt.write_str(self.as_str())
160 }
161}
162
163#[cfg(test)]
164mod tests {
165 #![expect(clippy::panic, clippy::unwrap_used, reason = "this is a test")]
166
167 use chrono::Datelike as _;
168
169 #[test]
170 fn test_weekday() {
171 for year in 2000_u16..=2171 {
174 'next_month: for month in 1_u8..=12 {
175 for day in 1_u8..=31 {
176 let Some(embedded_date) = crate::Date::new_checked(year, month, day) else {
177 continue 'next_month;
178 };
179 let chrono_date = chrono::NaiveDate::from_ymd_opt(
180 i32::from(year),
181 u32::from(month),
182 u32::from(day),
183 )
184 .unwrap();
185
186 let chrono_weekday = chrono_date.weekday();
187 let embedded_weekday = embedded_date.weekday();
188
189 match (chrono_weekday, embedded_weekday) {
190 (chrono::Weekday::Mon, super::Weekday::Mon)
191 | (chrono::Weekday::Tue, super::Weekday::Tue)
192 | (chrono::Weekday::Wed, super::Weekday::Wed)
193 | (chrono::Weekday::Thu, super::Weekday::Thu)
194 | (chrono::Weekday::Fri, super::Weekday::Fri)
195 | (chrono::Weekday::Sat, super::Weekday::Sat)
196 | (chrono::Weekday::Sun, super::Weekday::Sun) => (),
197 _ => panic!(
198 "chrono and embedded weekdays do not match: {chrono_weekday:?} != {embedded_weekday:?} for {chrono_date}"
199 ),
200 }
201
202 assert_eq!(
203 chrono_weekday.num_days_from_monday(),
204 u32::from(embedded_weekday.num_days_from_monday()),
205 "num_days_from_monday: {chrono_date}",
206 );
207
208 assert_eq!(
209 chrono_weekday.num_days_from_sunday(),
210 u32::from(embedded_weekday.num_days_from_sunday()),
211 "num_days_from_sunday: {chrono_date}",
212 );
213
214 assert_eq!(
215 chrono_weekday.number_from_monday(),
216 u32::from(embedded_weekday.number_from_monday()),
217 "number_from_monday: {chrono_date}",
218 );
219
220 assert_eq!(
221 chrono_weekday.number_from_sunday(),
222 u32::from(embedded_weekday.number_from_sunday()),
223 "number_from_sunday: {chrono_date}",
224 );
225 }
226 }
227 }
228 }
229}