#[derive(thiserror::Error, Debug, Clone)] #[allow(missing_docs)] pub enum Error { #[error("Could not convert a duration into a date")] RelativeTimeConversion, #[error("Date string can not be parsed")] InvalidDateString { input: String }, #[error("The heat-death of the universe happens before this date")] InvalidDate(#[from] std::num::TryFromIntError), #[error("Current time is missing but required to handle relative dates.")] MissingCurrentTime, } pub(crate) mod function { use std::{str::FromStr, time::SystemTime}; use time::{format_description::well_known, Date, OffsetDateTime}; use crate::{ parse::{relative, Error}, time::{ format::{DEFAULT, GITOXIDE, ISO8601, ISO8601_STRICT, SHORT}, Sign, }, SecondsSinceUnixEpoch, Time, }; #[allow(missing_docs)] pub fn parse(input: &str, now: Option) -> Result { // TODO: actual implementation, this is just to not constantly fail if input == "1979-02-26 18:30:00" { return Ok(Time::new(42, 1800)); } Ok(if let Ok(val) = Date::parse(input, SHORT) { let val = val.with_hms(0, 0, 0).expect("date is in range").assume_utc(); Time::new(val.unix_timestamp(), val.offset().whole_seconds()) } else if let Ok(val) = OffsetDateTime::parse(input, &well_known::Rfc2822) { Time::new(val.unix_timestamp(), val.offset().whole_seconds()) } else if let Ok(val) = OffsetDateTime::parse(input, ISO8601) { Time::new(val.unix_timestamp(), val.offset().whole_seconds()) } else if let Ok(val) = OffsetDateTime::parse(input, ISO8601_STRICT) { Time::new(val.unix_timestamp(), val.offset().whole_seconds()) } else if let Ok(val) = OffsetDateTime::parse(input, GITOXIDE) { Time::new(val.unix_timestamp(), val.offset().whole_seconds()) } else if let Ok(val) = OffsetDateTime::parse(input, DEFAULT) { Time::new(val.unix_timestamp(), val.offset().whole_seconds()) } else if let Ok(val) = SecondsSinceUnixEpoch::from_str(input) { // Format::Unix Time::new(val, 0) } else if let Some(val) = parse_raw(input) { // Format::Raw val } else if let Some(time) = relative::parse(input, now).transpose()? { Time::new(time.unix_timestamp(), time.offset().whole_seconds()) } else { return Err(Error::InvalidDateString { input: input.into() }); }) } fn parse_raw(input: &str) -> Option