diff --git a/src/gemtext/parser.rs b/src/gemtext/parser.rs index ee08f0c..3ae7bdd 100644 --- a/src/gemtext/parser.rs +++ b/src/gemtext/parser.rs @@ -1,4 +1,4 @@ -use crate::prelude::{Link, Mailbox, Recipients}; +use crate::prelude::{DateTime, Link, Mailbox, Recipients}; use std::fmt; #[derive(Debug)] @@ -18,7 +18,7 @@ enum State<'a> { pub enum GemtextNode { Sender(Mailbox), Recipients(Recipients), - Timestamp(String), + Timestamp(DateTime), Text(String), Heading1(String), Heading2(String), @@ -110,7 +110,11 @@ impl<'a> GemtextNode { let Some(line) = text.strip_prefix('@').map(|x| x.trim()) else { return Self::Text(text.to_string()); }; - Self::Timestamp(line.to_string()) + if let Ok(dt) = line.parse() { + Self::Timestamp(dt) + } else { + Self::Text(text.to_string()) + } } } @@ -326,7 +330,7 @@ mod tests { ); assert_eq!( nodes.next().cloned().unwrap(), - GemtextNode::Timestamp("2023-06-07T21:27:15Z".to_string()), + GemtextNode::Timestamp("2023-06-07T21:27:15Z".parse().unwrap()), ); assert_eq!( nodes.next().cloned().unwrap(), diff --git a/src/prelude.rs b/src/prelude.rs index 55b36cd..8b42b9f 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,7 +1,7 @@ pub use super::{ certificate::{Certificate, CertificateStore, ClientCertificateStore}, fingerprint::{Error as FingerprintError, Fingerprint, GetFingerprint}, - gemtext::{GemtextNode, Parser}, + gemtext::{GemtextNode, Parser as GemtextParser}, host::{Error as ParseHostError, Host}, mailbox::{Error as ParseMailboxError, Mailbox}, mailuser::Mailuser, @@ -14,4 +14,5 @@ pub use super::{ AuthenticationFailure, Error as ParseStatusError, PermanentFailure, Redirect, Status, TemporaryFailure, }, + time::{Error as ParseTimeError, DateTime, TimeZone, Sign, Parser as TimeParser}, }; diff --git a/src/time/mod.rs b/src/time/mod.rs index 2b5cda8..c7a57d5 100644 --- a/src/time/mod.rs +++ b/src/time/mod.rs @@ -120,6 +120,14 @@ impl PartialOrd for DateTime { } } +impl FromStr for DateTime { + type Err = Error; + + fn from_str(s: &str) -> Result { + Parser::new(s).parse() + } +} + impl DateTime { pub fn normalize(&self) -> Option { if self.tz == Some(TimeZone::UTC) { @@ -266,4 +274,22 @@ mod test { }; assert_eq!(dt.to_string(), "2023-05-07Z"); } + + #[test] + fn ordering() { + let mut dates = vec![ + "2023-06-10T10:01:52Z", + "2023-06-10T08:01:52+05", + "2023-06-10T11:30:30-05:15", + ]; + dates.sort_by(|a, b| a.partial_cmp(b).unwrap()); + assert_eq!( + dates, + vec![ + "2023-06-10T08:01:52+05", + "2023-06-10T10:01:52Z", + "2023-06-10T11:30:30-05:15", + ] + ) + } }