From 625bac1b629d7c8ed3c9f8e70a9a59085810c4a0 Mon Sep 17 00:00:00 2001 From: Cameron Eldridge Date: Wed, 1 Nov 2017 11:59:06 -0400 Subject: [PATCH] Add support for Z time zone and fractional seconds in date formats (#97) * Add support for Z time zone and fractional seconds in date formats and reduce repitition in tests --- juniper/src/integrations/chrono.rs | 76 +++++++++++++++++++++++------- juniper/src/integrations/mod.rs | 1 + 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/juniper/src/integrations/chrono.rs b/juniper/src/integrations/chrono.rs index 1ac62371..c02b84b9 100644 --- a/juniper/src/integrations/chrono.rs +++ b/juniper/src/integrations/chrono.rs @@ -18,7 +18,8 @@ use chrono::prelude::*; use ::Value; #[doc(hidden)] -pub static RFC3339_FORMAT: &'static str = "%Y-%m-%dT%H:%M:%S%z"; +pub static RFC3339_FORMAT: &'static str = "%Y-%m-%dT%H:%M:%S%.f%:z"; +static RFC3339_PARSE_FORMAT: &'static str = "%+"; graphql_scalar!(DateTime as "DateTimeFixedOffset" { description: "DateTime" @@ -60,7 +61,7 @@ graphql_scalar!(NaiveDate { from_input_value(v: &InputValue) -> Option { v.as_string_value() - .and_then(|s| NaiveDate::parse_from_str(s, RFC3339_FORMAT).ok()) + .and_then(|s| NaiveDate::parse_from_str(s, RFC3339_PARSE_FORMAT).ok()) } }); @@ -82,11 +83,9 @@ graphql_scalar!(NaiveDateTime { #[cfg(test)] mod test { use chrono::prelude::*; - use super::RFC3339_FORMAT; + use super::RFC3339_PARSE_FORMAT; - #[test] - fn datetime_fixedoffset_from_input_value() { - let raw = "2014-11-28T21:00:09+09:00"; + fn datetime_fixedoffset_test(raw: &'static str) { let input = ::InputValue::String(raw.to_string()); let parsed: DateTime = ::FromInputValue::from_input_value(&input).unwrap(); @@ -96,8 +95,21 @@ mod test { } #[test] - fn datetime_utc_from_input_value() { - let raw = "2014-11-28T21:00:09+09:00"; + fn datetime_fixedoffset_from_input_value() { + datetime_fixedoffset_test("2014-11-28T21:00:09+09:00"); + } + + #[test] + fn datetime_fixedoffset_from_input_value_with_z_timezone() { + datetime_fixedoffset_test("2014-11-28T21:00:09Z"); + } + + #[test] + fn datetime_fixedoffset_from_input_value_with_fractional_seconds() { + datetime_fixedoffset_test("2014-11-28T21:00:09.05+09:00"); + } + + fn datetime_utc_test(raw: &'static str) { let input = ::InputValue::String(raw.to_string()); let parsed: DateTime = ::FromInputValue::from_input_value(&input).unwrap(); @@ -107,22 +119,53 @@ mod test { } #[test] - fn naivedate_from_input_value() { - let raw = "1996-12-19T16:39:57-08:00"; + fn datetime_utc_from_input_value() { + datetime_utc_test("2014-11-28T21:00:09+09:00") + } + + #[test] + fn datetime_utc_from_input_value_with_z_timezone() { + datetime_utc_test("2014-11-28T21:00:09Z") + } + + #[test] + fn datetime_utc_from_input_value_with_fractional_seconds() { + datetime_utc_test("2014-11-28T21:00:09.005+09:00"); + } + + fn naivedate_test(raw: &'static str, y: i32, m: u32, d: u32) { let input = ::InputValue::String(raw.to_string()); let parsed: NaiveDate = ::FromInputValue::from_input_value(&input).unwrap(); - let expected = NaiveDate::parse_from_str(raw, &RFC3339_FORMAT).unwrap(); - let expected_via_datetime = DateTime::parse_from_rfc3339(raw).unwrap().date().naive_utc(); - let expected_via_ymd = NaiveDate::from_ymd(1996, 12, 19); + let expected = NaiveDate::parse_from_str(raw, &RFC3339_PARSE_FORMAT).unwrap(); + let expected_via_datetime = DateTime::parse_from_rfc3339(raw) + .unwrap() + .date() + .naive_utc(); + let expected_via_ymd = NaiveDate::from_ymd(y, m, d); assert_eq!(parsed, expected); assert_eq!(parsed, expected_via_datetime); assert_eq!(parsed, expected_via_ymd); - assert_eq!(parsed.year(), 1996); - assert_eq!(parsed.month(), 12); - assert_eq!(parsed.day(), 19); + assert_eq!(parsed.year(), y); + assert_eq!(parsed.month(), m); + assert_eq!(parsed.day(), d); + } + + #[test] + fn naivedate_from_input_value() { + naivedate_test("1996-12-19T16:39:57-08:00", 1996, 12, 19); + } + + #[test] + fn naivedate_from_input_value_with_fractional_seconds() { + naivedate_test("1996-12-19T16:39:57.005-08:00", 1996, 12, 19); + } + + #[test] + fn naivedate_from_input_value_with_z_timezone() { + naivedate_test("1996-12-19T16:39:57Z", 1996, 12, 19); } #[test] @@ -135,6 +178,5 @@ mod test { assert_eq!(parsed, expected); assert_eq!(raw, expected.timestamp() as f64); - } } diff --git a/juniper/src/integrations/mod.rs b/juniper/src/integrations/mod.rs index 2c9116f2..201f3f2d 100644 --- a/juniper/src/integrations/mod.rs +++ b/juniper/src/integrations/mod.rs @@ -1,3 +1,4 @@ +//! Provides GraphQLType implementations for some external types #[doc(hidden)] pub mod serde;