use std::str::FromStr;
#[derive(Debug, Clone)]
pub struct AmzDate {
year: u16,
month: u8,
day: u8,
hour: u8,
minute: u8,
second: u8,
}
#[derive(Debug, thiserror::Error)]
#[error("ParseAmzDateError")]
pub struct ParseAmzDateError {
_priv: (),
}
impl AmzDate {
pub fn parse(header: &str) -> Result<Self, ParseAmzDateError> {
fn nom_parse(input: &str) -> nom::IResult<&str, [&str; 6]> {
use nom::{
bytes::complete::{tag, take},
combinator::all_consuming,
sequence::tuple,
};
let mut parser = all_consuming(tuple((
take(4_usize),
take(2_usize),
take(2_usize),
tag("T"),
take(2_usize),
take(2_usize),
take(2_usize),
tag("Z"),
)));
let (_, (year_str, month_str, day_str, _, hour_str, minute_str, second_str, _)) = parser(input)?;
Ok((input, [year_str, month_str, day_str, hour_str, minute_str, second_str]))
}
fn to_num<T: FromStr>(input: &str) -> Result<T, ParseAmzDateError> {
match input.parse::<T>() {
Ok(x) => Ok(x),
Err(_) => Err(ParseAmzDateError { _priv: () }),
}
}
match nom_parse(header) {
Err(_) => Err(ParseAmzDateError { _priv: () }),
Ok((_, [year_str, month_str, day_str, hour_str, minute_str, second_str])) => Ok(Self {
year: to_num(year_str)?,
month: to_num(month_str)?,
day: to_num(day_str)?,
hour: to_num(hour_str)?,
minute: to_num(minute_str)?,
second: to_num(second_str)?,
}),
}
}
#[must_use]
pub fn to_iso8601(&self) -> String {
format!(
"{:04}{:02}{:02}T{:02}{:02}{:02}Z",
self.year, self.month, self.day, self.hour, self.minute, self.second
)
}
#[must_use]
pub fn to_date(&self) -> String {
format!("{:04}{:02}{:02}", self.year, self.month, self.day,)
}
}