From 9fdd2c32103569308343bea0e3c28a07946f70ab Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Mon, 24 Apr 2023 11:24:14 +0200 Subject: [PATCH] Do not use `Offset`'s `Debug` impl when serializing `DateTime` --- src/datetime/mod.rs | 4 +++- src/datetime/rustc_serialize.rs | 4 ++-- src/datetime/serde.rs | 22 ++++++++++++---------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index d2a0c9b611..a36ac6ecd1 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -1418,7 +1418,9 @@ where &FixedOffset::east_opt(3650).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap() ) .ok(), - Some(r#""2014-07-24T12:34:06+01:00:50""#.into()) + // Seconds are not allowed by RFC 3339, offset should be rounded to the nearest minute. + // In this case `+01:00:50` becomes `+01:01` + Some(r#""2014-07-24T12:34:06+01:01""#.into()) ); } diff --git a/src/datetime/rustc_serialize.rs b/src/datetime/rustc_serialize.rs index 8e75350d92..115ec9eb3f 100644 --- a/src/datetime/rustc_serialize.rs +++ b/src/datetime/rustc_serialize.rs @@ -1,6 +1,6 @@ #![cfg_attr(docsrs, doc(cfg(feature = "rustc-serialize")))] -use super::DateTime; +use super::{DateTime, SecondsFormat}; #[cfg(feature = "clock")] use crate::offset::Local; use crate::offset::{FixedOffset, LocalResult, TimeZone, Utc}; @@ -10,7 +10,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; impl Encodable for DateTime { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - format!("{:?}", self).encode(s) + self.to_rfc3339_opts(SecondsFormat::AutoSi, true).encode(s) } } diff --git a/src/datetime/serde.rs b/src/datetime/serde.rs index 0715959679..61f7f68840 100644 --- a/src/datetime/serde.rs +++ b/src/datetime/serde.rs @@ -3,11 +3,12 @@ use core::fmt; use serde::{de, ser}; -use super::DateTime; +use super::{DateTime, SecondsFormat}; +use crate::format::write_rfc3339; use crate::naive::datetime::serde::serde_from; #[cfg(feature = "clock")] use crate::offset::Local; -use crate::offset::{FixedOffset, TimeZone, Utc}; +use crate::offset::{FixedOffset, Offset, TimeZone, Utc}; #[doc(hidden)] #[derive(Debug)] @@ -25,7 +26,7 @@ pub struct MicroSecondsTimestampVisitor; #[derive(Debug)] pub struct MilliSecondsTimestampVisitor; -/// Serialize into a rfc3339 time string +/// Serialize into an ISO 8601 formatted string. /// /// See [the `serde` module](./serde/index.html) for alternate /// serializations. @@ -34,18 +35,19 @@ impl ser::Serialize for DateTime { where S: ser::Serializer, { - struct FormatWrapped<'a, D: 'a> { - inner: &'a D, + struct FormatIso8601<'a, Tz: TimeZone> { + inner: &'a DateTime, } - impl<'a, D: fmt::Debug> fmt::Display for FormatWrapped<'a, D> { + impl<'a, Tz: TimeZone> fmt::Display for FormatIso8601<'a, Tz> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(f) + let naive = self.inner.naive_local(); + let offset = self.inner.offset.fix(); + write_rfc3339(f, naive, offset, SecondsFormat::AutoSi, true) } } - // Debug formatting is correct RFC3339, and it allows Zulu. - serializer.collect_str(&FormatWrapped { inner: &self }) + serializer.collect_str(&FormatIso8601 { inner: self }) } } @@ -1151,11 +1153,11 @@ pub mod ts_seconds_option { #[cfg(test)] mod tests { - use core::fmt; #[cfg(feature = "clock")] use crate::datetime::test_decodable_json; use crate::datetime::test_encodable_json; use crate::{DateTime, FixedOffset, TimeZone, Utc}; + use core::fmt; #[test] fn test_serde_serialize() {