From f8cd5d8c45e0256df2a476f3019c5eb4b008091e Mon Sep 17 00:00:00 2001 From: NYBACHOK Date: Fri, 1 Nov 2024 14:15:39 +0200 Subject: [PATCH] date parsing --- process/at.rs | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/process/at.rs b/process/at.rs index d2af4901..0b99c9e4 100644 --- a/process/at.rs +++ b/process/at.rs @@ -334,6 +334,8 @@ mod time { mod timespec { use std::str::FromStr; + use crate::tokens::{DayNumber, DayOfWeek, MonthName, TokenParsingError, YearNumber}; + // TODO: Proper errors for each case and token #[derive(Debug, PartialEq)] pub struct TimespecParsingError; @@ -356,6 +358,12 @@ mod timespec { } } + impl From for TimespecParsingError { + fn from(_value: TokenParsingError) -> Self { + Self + } + } + pub enum IncPeriod { Minute, Minutes, @@ -431,6 +439,81 @@ mod timespec { Ok(result) } } + + pub enum Date { + MontDay { + month_name: MonthName, + day_number: DayNumber, + }, + MontDayYear { + month_name: MonthName, + day_number: DayNumber, + year_number: YearNumber, + }, + DayOfWeek(DayOfWeek), + Today, + Tomorrow, + } + + impl FromStr for Date { + type Err = TimespecParsingError; + + fn from_str(s: &str) -> Result { + let result = match s { + "today" => Self::Today, + "tomorrow" => Self::Tomorrow, + _ => match s.contains(",") { + true => { + let parts = s.split(',').collect::>(); + + if parts.len() != 2 { + Err(TimespecParsingError)? + } + + let (month_name, day_number) = parse_month_and_day(&parts[0])?; + let year_number = YearNumber::from_str(&parts[1])?; + + Self::MontDayYear { + month_name, + day_number, + year_number, + } + } + false => match DayOfWeek::from_str(s) { + Ok(day) => Self::DayOfWeek(day), + Err(_) => { + let (month_name, day_number) = parse_month_and_day(s)?; + + Self::MontDay { + month_name, + day_number, + } + } + }, + }, + }; + + fn parse_month_and_day( + s: &str, + ) -> Result<(MonthName, DayNumber), TimespecParsingError> { + let month = s + .chars() + .take_while(|this| !this.is_numeric()) + .collect::() + .parse::()?; + + let day = s + .chars() + .skip_while(|this| !this.is_numeric()) + .collect::() + .parse::()?; + + Ok((month, day)) + } + + Ok(result) + } + } } mod tokens { @@ -701,14 +784,38 @@ mod tokens { /// implementation-defined format. pub struct TimezoneName(String); + impl FromStr for TimezoneName { + type Err = TokenParsingError; + + fn from_str(s: &str) -> Result { + todo!() + } + } + /// One of the values from the mon or abmon keywords in the LC_TIME /// locale category. pub struct MonthName(String); + impl FromStr for MonthName { + type Err = TokenParsingError; + + fn from_str(s: &str) -> Result { + todo!() + } + } + /// One of the values from the day or abday keywords in the LC_TIME /// locale category. pub struct DayOfWeek(String); + impl FromStr for DayOfWeek { + type Err = TokenParsingError; + + fn from_str(s: &str) -> Result { + todo!() + } + } + /// One of the values from the am_pm keyword in the LC_TIME locale /// category. pub enum AmPm { @@ -716,6 +823,18 @@ mod tokens { Pm, } + impl FromStr for AmPm { + type Err = TokenParsingError; + + fn from_str(s: &str) -> Result { + Ok(match s.to_lowercase().as_str() { + "am" => Self::Am, + "pm" => Self::Pm, + _ => Err(TokenParsingError)?, + }) + } + } + #[cfg(test)] mod test { use super::*;