diff --git a/instant-xml/Cargo.toml b/instant-xml/Cargo.toml index 2c0974d..af1b0a6 100644 --- a/instant-xml/Cargo.toml +++ b/instant-xml/Cargo.toml @@ -6,6 +6,7 @@ workspace = ".." license = "Apache-2.0 OR MIT" [dependencies] +chrono = { version = "0.4.23", optional = true } macros = { package = "instant-xml-macros", version = "0.1", path = "../instant-xml-macros" } thiserror = "1.0.29" xmlparser = "0.13.3" diff --git a/instant-xml/src/impls.rs b/instant-xml/src/impls.rs index cd054a1..edd09bd 100644 --- a/instant-xml/src/impls.rs +++ b/instant-xml/src/impls.rs @@ -2,6 +2,9 @@ use std::borrow::Cow; use std::fmt; use std::str::FromStr; +#[cfg(feature = "chrono")] +use chrono::{DateTime, Utc}; + use crate::{de::Node, Deserializer, Error, FromXml, Kind, Serializer, ToXml}; // Deserializer @@ -393,3 +396,28 @@ where const KIND: Kind = Kind::Vec; } + +#[cfg(feature = "chrono")] +impl ToXml for DateTime { + fn serialize( + &self, + serializer: &mut Serializer, + ) -> Result<(), Error> { + serializer.write_str(&self.to_rfc3339()) + } + + const KIND: Kind = Kind::Scalar; +} + +#[cfg(feature = "chrono")] +impl<'xml> FromXml<'xml> for DateTime { + fn deserialize<'cx>(deserializer: &'cx mut Deserializer<'cx, 'xml>) -> Result { + let data = deserializer.take_str()?; + match DateTime::parse_from_rfc3339(data) { + Ok(dt) if dt.timezone().utc_minus_local() == 0 => Ok(dt.with_timezone(&Utc)), + _ => Err(Error::Other("invalid date/time".into())), + } + } + + const KIND: Kind = Kind::Scalar; +} diff --git a/instant-xml/tests/chrono.rs b/instant-xml/tests/chrono.rs new file mode 100644 index 0000000..0ad6276 --- /dev/null +++ b/instant-xml/tests/chrono.rs @@ -0,0 +1,21 @@ +#![cfg(feature = "chrono")] + +use chrono::{DateTime, TimeZone, Utc}; +use instant_xml::{from_str, to_string, FromXml, ToXml}; + +#[derive(Debug, Eq, PartialEq, FromXml, ToXml)] +struct Test { + dt: DateTime, +} + +#[test] +fn datetime() { + let dt = Utc.with_ymd_and_hms(2022, 11, 21, 21, 17, 23).unwrap(); + let test = Test { dt }; + let xml = "
2022-11-21T21:17:23+00:00
"; + assert_eq!(to_string(&test).unwrap(), xml); + assert_eq!(from_str::(xml).unwrap(), test); + + let zulu = xml.replace("+00:00", "Z"); + assert_eq!(from_str::(&zulu).unwrap(), test); +}