diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index 5e693ea5..366bbe6a 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -1933,89 +1933,3 @@ where /// -------- /// 719163 const UNIX_EPOCH_DAY: i64 = 719_163; - -#[cfg(all(test, feature = "serde"))] -fn test_encodable_json(to_string_utc: FUtc, to_string_fixed: FFixed) -where - FUtc: Fn(&DateTime) -> Result, - FFixed: Fn(&DateTime) -> Result, - E: ::core::fmt::Debug, -{ - assert_eq!( - to_string_utc(&Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()).ok(), - Some(r#""2014-07-24T12:34:06Z""#.into()) - ); - - assert_eq!( - to_string_fixed( - &FixedOffset::east_opt(3660).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap() - ) - .ok(), - Some(r#""2014-07-24T12:34:06+01:01""#.into()) - ); - assert_eq!( - to_string_fixed( - &FixedOffset::east_opt(3650).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap() - ) - .ok(), - // An offset with seconds is not allowed by RFC 3339, so we round it to the nearest minute. - // In this case `+01:00:50` becomes `+01:01` - Some(r#""2014-07-24T12:34:06+01:01""#.into()) - ); -} - -#[cfg(all(test, feature = "clock", feature = "serde"))] -fn test_decodable_json( - utc_from_str: FUtc, - fixed_from_str: FFixed, - local_from_str: FLocal, -) where - FUtc: Fn(&str) -> Result, E>, - FFixed: Fn(&str) -> Result, E>, - FLocal: Fn(&str) -> Result, E>, - E: ::core::fmt::Debug, -{ - // should check against the offset as well (the normal DateTime comparison will ignore them) - fn norm(dt: &Option>) -> Option<(&DateTime, &Tz::Offset)> { - dt.as_ref().map(|dt| (dt, dt.offset())) - } - - assert_eq!( - norm(&utc_from_str(r#""2014-07-24T12:34:06Z""#).ok()), - norm(&Some(Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap())) - ); - assert_eq!( - norm(&utc_from_str(r#""2014-07-24T13:57:06+01:23""#).ok()), - norm(&Some(Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap())) - ); - - assert_eq!( - norm(&fixed_from_str(r#""2014-07-24T12:34:06Z""#).ok()), - norm(&Some( - FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap() - )) - ); - assert_eq!( - norm(&fixed_from_str(r#""2014-07-24T13:57:06+01:23""#).ok()), - norm(&Some( - FixedOffset::east_opt(60 * 60 + 23 * 60) - .unwrap() - .with_ymd_and_hms(2014, 7, 24, 13, 57, 6) - .unwrap() - )) - ); - - // we don't know the exact local offset but we can check that - // the conversion didn't change the instant itself - assert_eq!( - local_from_str(r#""2014-07-24T12:34:06Z""#).expect("local should parse"), - Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap() - ); - assert_eq!( - local_from_str(r#""2014-07-24T13:57:06+01:23""#).expect("local should parse with offset"), - Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap() - ); - - assert!(utc_from_str(r#""2014-07-32T12:34:06Z""#).is_err()); - assert!(fixed_from_str(r#""2014-07-32T12:34:06Z""#).is_err()); -} diff --git a/src/datetime/serde.rs b/src/datetime/serde.rs index 724c1ae7..6f048a45 100644 --- a/src/datetime/serde.rs +++ b/src/datetime/serde.rs @@ -1209,24 +1209,87 @@ pub mod ts_seconds_option { #[cfg(test)] mod tests { #[cfg(feature = "clock")] - use crate::datetime::test_decodable_json; - use crate::datetime::test_encodable_json; + use crate::Local; use crate::{DateTime, FixedOffset, TimeZone, Utc}; use core::fmt; #[test] fn test_serde_serialize() { - test_encodable_json(serde_json::to_string, serde_json::to_string); + assert_eq!( + serde_json::to_string(&Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()).ok(), + Some(r#""2014-07-24T12:34:06Z""#.to_owned()) + ); + assert_eq!( + serde_json::to_string( + &FixedOffset::east_opt(3660) + .unwrap() + .with_ymd_and_hms(2014, 7, 24, 12, 34, 6) + .unwrap() + ) + .ok(), + Some(r#""2014-07-24T12:34:06+01:01""#.to_owned()) + ); + assert_eq!( + serde_json::to_string( + &FixedOffset::east_opt(3650) + .unwrap() + .with_ymd_and_hms(2014, 7, 24, 12, 34, 6) + .unwrap() + ) + .ok(), + // An offset with seconds is not allowed by RFC 3339, so we round it to the nearest minute. + // In this case `+01:00:50` becomes `+01:01` + Some(r#""2014-07-24T12:34:06+01:01""#.to_owned()) + ); } - #[cfg(feature = "clock")] #[test] fn test_serde_deserialize() { - test_decodable_json( - |input| serde_json::from_str(input), - |input| serde_json::from_str(input), - |input| serde_json::from_str(input), + // should check against the offset as well (the normal DateTime comparison will ignore them) + fn norm(dt: &Option>) -> Option<(&DateTime, &Tz::Offset)> { + dt.as_ref().map(|dt| (dt, dt.offset())) + } + + let dt: Option> = serde_json::from_str(r#""2014-07-24T12:34:06Z""#).ok(); + assert_eq!(norm(&dt), norm(&Some(Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()))); + let dt: Option> = serde_json::from_str(r#""2014-07-24T13:57:06+01:23""#).ok(); + assert_eq!(norm(&dt), norm(&Some(Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()))); + + let dt: Option> = + serde_json::from_str(r#""2014-07-24T12:34:06Z""#).ok(); + assert_eq!( + norm(&dt), + norm(&Some( + FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap() + )) ); + let dt: Option> = + serde_json::from_str(r#""2014-07-24T13:57:06+01:23""#).ok(); + assert_eq!( + norm(&dt), + norm(&Some( + FixedOffset::east_opt(60 * 60 + 23 * 60) + .unwrap() + .with_ymd_and_hms(2014, 7, 24, 13, 57, 6) + .unwrap() + )) + ); + + // we don't know the exact local offset but we can check that + // the conversion didn't change the instant itself + #[cfg(feature = "clock")] + { + let dt: DateTime = + serde_json::from_str(r#""2014-07-24T12:34:06Z""#).expect("local should parse"); + assert_eq!(dt, Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()); + + let dt: DateTime = serde_json::from_str(r#""2014-07-24T13:57:06+01:23""#) + .expect("local should parse with offset"); + assert_eq!(dt, Utc.with_ymd_and_hms(2014, 7, 24, 12, 34, 6).unwrap()); + } + + assert!(serde_json::from_str::>(r#""2014-07-32T12:34:06Z""#).is_err()); + assert!(serde_json::from_str::>(r#""2014-07-32T12:34:06Z""#).is_err()); } #[test]