diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/month.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/month.rs b/src/month.rs index f97a6fc..66360ef 100644 --- a/src/month.rs +++ b/src/month.rs @@ -2,9 +2,12 @@ use derive_more::Display; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +use thiserror::Error; use self::Month::*; +use core::str::FromStr; + /// Months of the year #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -54,6 +57,66 @@ impl Month { } } + /// Get the month from the given string, + /// which is assumed to be the month's abbreviation. + /// Returns `None` if the string is not a valid abbrevation of a month + /// + /// # Example + /// + /// ``` + /// use botic::Month; + /// + /// assert_eq!(Some(Month::January), Month::from_abbreviation("Jan")); + /// assert_eq!(None, Month::from_abbreviation("Janu")); + /// ``` + pub fn from_abbreviation(abbreviation: &str) -> Option<Self> { + match abbreviation { + "Jan" => Some(January), + "Feb" => Some(February), + "Mar" => Some(March), + "Apr" => Some(April), + "May" => Some(May), + "Jun" => Some(June), + "Jul" => Some(July), + "Aug" => Some(August), + "Sep" => Some(September), + "Oct" => Some(October), + "Nov" => Some(November), + "Dec" => Some(December), + _ => None, + } + } + + /// Get the month from the given string, + /// which is assumed to be the month's name. + /// Returns `None` if the string is not a valid month + /// + /// # Example + /// + /// ``` + /// use botic::Month; + /// + /// assert_eq!(Some(Month::January), Month::from_name("January")); + /// assert_eq!(None, Month::from_name("Janu")); + /// ``` + pub fn from_name(name: &str) -> Option<Self> { + match name { + "January" => Some(January), + "February" => Some(February), + "March" => Some(March), + "April" => Some(April), + "May" => Some(May), + "June" => Some(June), + "July" => Some(July), + "August" => Some(August), + "September" => Some(September), + "October" => Some(October), + "November" => Some(November), + "December" => Some(December), + _ => None, + } + } + /// Get the number of the month /// /// # Example @@ -173,3 +236,30 @@ impl From<Month> for u8 { month as u8 } } + +#[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 ParseMonthError; + +// TODO optimize to look like this: https://github.com/chronotope/chrono/blob/main/src/format/scan.rs#L102 +// TODO make case-insensitive +impl FromStr for Month { + type Err = ParseMonthError; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + if let Ok(num) = u8::from_str(s) { + if let Some(month) = Month::from_u8(num) { + Ok(month) + } else { + Err(ParseMonthError) + } + } else if let Some(month) = Month::from_abbreviation(s) { + Ok(month) + } else if let Some(month) = Month::from_name(s) { + Ok(month) + } else { + Err(ParseMonthError) + } + } +} |
