summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/month.rs90
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)
+ }
+ }
+}