summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBotahamec <botahamec@outlook.com>2021-12-27 16:50:28 -0500
committerBotahamec <botahamec@outlook.com>2021-12-27 16:50:28 -0500
commit9bb6f9a5b3b96f5797d870e01a799ae0553058af (patch)
treec905943cfac464efc3ac644f5f5319d5f6dbf336 /src
parentdc08e7b94daaf33e06f2cfa2a146cac0d5901f27 (diff)
Add weekdays
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs2
-rw-r--r--src/weekday.rs176
2 files changed, 178 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index c1bd251..fdfeb5c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,9 @@
#![doc = include_str!("../README.md")]
mod month;
+mod weekday;
mod year;
pub use month::Month;
+pub use weekday::Weekday;
pub use year::Year;
diff --git a/src/weekday.rs b/src/weekday.rs
new file mode 100644
index 0000000..5679bc7
--- /dev/null
+++ b/src/weekday.rs
@@ -0,0 +1,176 @@
+use std::str::FromStr;
+
+use derive_more::Display;
+
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Serialize};
+use thiserror::Error;
+
+use self::Weekday::*;
+
+/// Day of the week
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[repr(u8)]
+pub enum Weekday {
+ Monday = 0,
+ Tuesday = 1,
+ Wednesday = 2,
+ Thursday = 3,
+ Friday = 4,
+ Saturday = 5,
+ Sunday = 6,
+}
+
+impl Weekday {
+ /// Get the weekday from its name. Returns `None` if an invalid name was given.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use botic::Weekday;
+ ///
+ /// assert_eq!(Weekday::Monday, Weekday::from_name("Monday").unwrap());
+ /// assert_eq!(None, Weekday::from_name("monday"));
+ /// ```
+ pub fn from_name(name: &str) -> Option<Self> {
+ match name {
+ "Monday" => Some(Monday),
+ "Tuesday" => Some(Tuesday),
+ "Wednesday" => Some(Wednesday),
+ "Thursday" => Some(Thursday),
+ "Friday" => Some(Friday),
+ "Saturday" => Some(Saturday),
+ "Sunday" => Some(Sunday),
+ _ => None,
+ }
+ }
+
+ /// Get the next weekday
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use botic::Weekday;
+ ///
+ /// assert_eq!(Weekday::Tuesday, Weekday::Monday.next());
+ /// ```
+ pub const fn next(self) -> Self {
+ match self {
+ Monday => Tuesday,
+ Tuesday => Wednesday,
+ Wednesday => Thursday,
+ Thursday => Friday,
+ Friday => Saturday,
+ Saturday => Sunday,
+ Sunday => Monday,
+ }
+ }
+
+ /// Get the previous weekday
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use botic::Weekday;
+ ///
+ /// assert_eq!(Weekday::Sunday, Weekday::Monday.previous());
+ /// ```
+ pub const fn previous(self) -> Self {
+ match self {
+ Monday => Sunday,
+ Tuesday => Monday,
+ Wednesday => Tuesday,
+ Thursday => Wednesday,
+ Friday => Thursday,
+ Saturday => Friday,
+ Sunday => Saturday,
+ }
+ }
+
+ /// Get the zero-indexed number of days from Monday.
+ /// In other words, the number representing the day of the week,
+ /// starting with Monday = 0
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use botic::Weekday;
+ ///
+ /// assert_eq!(0, Weekday::Monday.number_days_from_monday());
+ /// assert_eq!(6, Weekday::Sunday.number_days_from_monday());
+ /// ```
+ pub const fn number_days_from_monday(self) -> u8 {
+ self as u8
+ }
+
+ /// Get the one-indexed number of days from Monday.
+ /// In other words, the number representing the day of the week,
+ /// starting with Monday = 1
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use botic::Weekday;
+ ///
+ /// assert_eq!(1, Weekday::Monday.number_from_monday());
+ /// assert_eq!(7, Weekday::Sunday.number_from_monday());
+ /// ```
+ pub const fn number_from_monday(self) -> u8 {
+ self.number_days_from_monday() + 1
+ }
+
+ /// Get the zero-indexed number of days from Sunday.
+ /// In other words, the number representing the day of the week,
+ /// starting with Sunday = 0
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use botic::Weekday;
+ ///
+ /// assert_eq!(0, Weekday::Sunday.number_days_from_sunday());
+ /// assert_eq!(1, Weekday::Monday.number_days_from_sunday());
+ /// ```
+ // TODO benchmark this
+ pub const fn number_days_from_sunday(self) -> u8 {
+ match self {
+ Sunday => 0,
+ _ => (self as u8) + 1,
+ }
+ }
+
+ /// Get the one-indexed number of days from Sunday.
+ /// In other words, the number representing the day of the week,
+ /// starting with Sunday = 1
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use botic::Weekday;
+ ///
+ /// assert_eq!(1, Weekday::Sunday.number_from_sunday());
+ /// assert_eq!(2, Weekday::Monday.number_from_sunday());
+ /// ```
+ pub const fn number_from_sunday(self) -> u8 {
+ self.number_days_from_sunday() + 1
+ }
+}
+
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Error)]
+#[error("Failed to parse the month")]
+// TODO Consider trying to figure out what month the user meant to use
+pub struct ParseWeekdayError;
+
+// TODO make case-insensitive
+// TODO support short names
+impl FromStr for Weekday {
+ type Err = ParseWeekdayError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match Self::from_name(s) {
+ Some(weekday) => Ok(weekday),
+ None => Err(ParseWeekdayError),
+ }
+ }
+}