From d2bf1494b1664113b9ee3250b33dc335fd7a01c1 Mon Sep 17 00:00:00 2001 From: David Kellum Date: Thu, 11 Jan 2018 15:50:57 -0800 Subject: [PATCH 1/6] Add DateTime to_rfc3339p(z) methods, tests These additions allow convenient control of RFC 3339 formatted output: * Number of subsecond digits to display * Whether to use the 'Z' variant, instead of "+00:00" for TZ offset 0, UTC. ...while remaining faithful to the RFC 3339. The implementation uses the existing formatting Item mechanism. github: cc: #157 #178 --- src/datetime.rs | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/src/datetime.rs b/src/datetime.rs index 6500ee7..2e6c194 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -246,6 +246,23 @@ impl DateTime where Tz::Offset: fmt::Display { self.format_with_items(ITEMS.iter().cloned()).to_string() } + /// Return an RFC 3339 and ISO 8601 date and time with subseconds formatted + /// as per a Fixed variant or None for no subseconds. The Fixed + /// variants supported are: Nanosecond, Nanosecond3, Nanosecond6 + /// and Nanosecond9. Other values will panic! + pub fn to_rfc3339p(&self, subform: Option) -> String { + self.rfc3339_via_items(subform, false) + } + + /// Return an RFC 3339 and ISO 8601 date and time with subseconds formatted + /// as per a Fixed variant or None for no subseconds. The Fixed + /// variants supported are: Nanosecond, Nanosecond3, Nanosecond6 + /// and Nanosecond9. Other values will panic! + /// If the timezone is UTC (offset 0), use 'Z'. + pub fn to_rfc3339pz(&self, subform: Option) -> String { + self.rfc3339_via_items(subform, true) + } + /// Formats the combined date and time with the specified formatting items. #[inline] pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat @@ -261,6 +278,54 @@ impl DateTime where Tz::Offset: fmt::Display { pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat> { self.format_with_items(StrftimeItems::new(fmt)) } + + fn rfc3339_via_items(&self, subform: Option, use_z: bool) -> String + { + use format::Item::*; + use format::Numeric::*; + use format::Pad::Zero; + use format::Fixed::*; + use format::Fixed::Nanosecond; + + static PREFIX: &[Item<'static>] = &[ + Numeric(Year, Zero), + Literal("-"), + Numeric(Month, Zero), + Literal("-"), + Numeric(Day, Zero), + Literal("T"), + Numeric(Hour, Zero), + Literal(":"), + Numeric(Minute, Zero), + Literal(":"), + Numeric(Second, Zero), + ]; + + let ssitem = match subform { + None => None, + Some(sf) => match sf { + Nanosecond | + Nanosecond3 | Nanosecond6 | Nanosecond9 => Some(Fixed(sf)), + _ => panic!("Unsupported rfc_3339p subsecond format {:?}", sf) + } + }; + + let tzitem = Fixed(match use_z { + true => TimezoneOffsetColonZ, + false => TimezoneOffsetColon + }); + + match ssitem { + None => + self.format_with_items( + PREFIX.iter().chain([tzitem].iter()).cloned() + ).to_string(), + Some(s) => + self.format_with_items( + PREFIX.iter().chain([s, tzitem].iter()).cloned() + ).to_string(), + } + } } impl Datelike for DateTime { @@ -1059,6 +1124,36 @@ mod tests { Ok(EDT.ymd(2015, 2, 18).and_hms_micro(23, 59, 59, 1_234_567))); } + #[test] + fn test_rfc3339p_and_z() { + use format::Fixed::*; + let pst = FixedOffset::east(8*60*60); + let dt = pst.ymd(2018, 1, 11).and_hms_nano(10, 5, 13, 84_660_684); + assert_eq!("2018-01-11T10:05:13+08:00", dt.to_rfc3339p (None)); + assert_eq!("2018-01-11T10:05:13+08:00", dt.to_rfc3339pz(None)); + assert_eq!("2018-01-11T10:05:13.084+08:00", dt.to_rfc3339p (Some(Nanosecond3))); + assert_eq!("2018-01-11T10:05:13.084660+08:00", dt.to_rfc3339p (Some(Nanosecond6))); + assert_eq!("2018-01-11T10:05:13.084660684+08:00", dt.to_rfc3339p (Some(Nanosecond9))); + assert_eq!("2018-01-11T10:05:13.084660684+08:00", dt.to_rfc3339p (Some(Nanosecond))); + + let ut = DateTime::::from_utc( dt.naive_utc(), Utc ); + assert_eq!("2018-01-11T02:05:13+00:00", ut.to_rfc3339p (None)); + assert_eq!("2018-01-11T02:05:13Z", ut.to_rfc3339pz(None)); + assert_eq!("2018-01-11T02:05:13.084+00:00", ut.to_rfc3339p (Some(Nanosecond3))); + assert_eq!("2018-01-11T02:05:13.084Z", ut.to_rfc3339pz(Some(Nanosecond3))); + assert_eq!("2018-01-11T02:05:13.084660Z", ut.to_rfc3339pz(Some(Nanosecond6))); + assert_eq!("2018-01-11T02:05:13.084660684Z", ut.to_rfc3339pz(Some(Nanosecond9))); + assert_eq!("2018-01-11T02:05:13.084660684Z", ut.to_rfc3339pz(Some(Nanosecond))); + } + + #[test] + #[should_panic] + fn test_rfc3339p_fixed_bogus_n() { + use format::Fixed::*; + let now = Utc::now(); + println!("{}", now.to_rfc3339p(Some(UpperAmPm))); + } + #[test] fn test_datetime_from_str() { assert_eq!("2015-2-18T23:16:9.15Z".parse::>(), From 353a7bbbc4f95cb15ee385c70843fd6102f82410 Mon Sep 17 00:00:00 2001 From: David Kellum Date: Fri, 12 Jan 2018 14:38:00 -0800 Subject: [PATCH 2/6] Use const for compat with rustc 1.13-16 Was using static but that's only supported as of rustc 1.17 (rust these older versions. Also continue using the copious explicit 'static lifetimes for the same compatibility, despite the clippy lint. --- src/datetime.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datetime.rs b/src/datetime.rs index 2e6c194..a03b42b 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -287,7 +287,7 @@ impl DateTime where Tz::Offset: fmt::Display { use format::Fixed::*; use format::Fixed::Nanosecond; - static PREFIX: &[Item<'static>] = &[ + const PREFIX: &'static [Item<'static>] = &[ Numeric(Year, Zero), Literal("-"), Numeric(Month, Zero), From 0e6d1d49b70d7b41f445044d2d3aeebdf3d614d6 Mon Sep 17 00:00:00 2001 From: David Kellum Date: Fri, 12 Jan 2018 16:08:34 -0800 Subject: [PATCH 3/6] cleanup name resolution for backward compatibility so it builds with rustc 1.13 --- src/datetime.rs | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/datetime.rs b/src/datetime.rs index a03b42b..41f30b3 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -281,38 +281,37 @@ impl DateTime where Tz::Offset: fmt::Display { fn rfc3339_via_items(&self, subform: Option, use_z: bool) -> String { - use format::Item::*; use format::Numeric::*; use format::Pad::Zero; - use format::Fixed::*; - use format::Fixed::Nanosecond; const PREFIX: &'static [Item<'static>] = &[ - Numeric(Year, Zero), - Literal("-"), - Numeric(Month, Zero), - Literal("-"), - Numeric(Day, Zero), - Literal("T"), - Numeric(Hour, Zero), - Literal(":"), - Numeric(Minute, Zero), - Literal(":"), - Numeric(Second, Zero), + Item::Numeric(Year, Zero), + Item::Literal("-"), + Item::Numeric(Month, Zero), + Item::Literal("-"), + Item::Numeric(Day, Zero), + Item::Literal("T"), + Item::Numeric(Hour, Zero), + Item::Literal(":"), + Item::Numeric(Minute, Zero), + Item::Literal(":"), + Item::Numeric(Second, Zero), ]; let ssitem = match subform { None => None, Some(sf) => match sf { - Nanosecond | - Nanosecond3 | Nanosecond6 | Nanosecond9 => Some(Fixed(sf)), + Fixed::Nanosecond | + Fixed::Nanosecond3 | + Fixed::Nanosecond6 | + Fixed::Nanosecond9 => Some(Item::Fixed(sf)), _ => panic!("Unsupported rfc_3339p subsecond format {:?}", sf) } }; - let tzitem = Fixed(match use_z { - true => TimezoneOffsetColonZ, - false => TimezoneOffsetColon + let tzitem = Item::Fixed(match use_z { + true => Fixed::TimezoneOffsetColonZ, + false => Fixed::TimezoneOffsetColon }); match ssitem { From efb0f3b01565abaf44c49d1dac96c63ba8ef59af Mon Sep 17 00:00:00 2001 From: David Kellum Date: Fri, 12 Jan 2018 16:19:26 -0800 Subject: [PATCH 4/6] Clippy no likey a match on bool --- src/datetime.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/datetime.rs b/src/datetime.rs index 41f30b3..7ed0d31 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -309,10 +309,13 @@ impl DateTime where Tz::Offset: fmt::Display { } }; - let tzitem = Item::Fixed(match use_z { - true => Fixed::TimezoneOffsetColonZ, - false => Fixed::TimezoneOffsetColon - }); + let tzitem = Item::Fixed( + if use_z { + Fixed::TimezoneOffsetColonZ + } else { + Fixed::TimezoneOffsetColon + } + ); match ssitem { None => From 1a0ebe7e30a7e55af8cfee0b98dfbb2a1a4dbd10 Mon Sep 17 00:00:00 2001 From: David Kellum Date: Thu, 25 Jan 2018 14:23:30 -0800 Subject: [PATCH 5/6] Add more specific SecondsFormat and offer single to_rfc3339_opts --- src/datetime.rs | 137 ++++++++++++++++++++++++------------------------ src/lib.rs | 4 +- 2 files changed, 70 insertions(+), 71 deletions(-) diff --git a/src/datetime.rs b/src/datetime.rs index 7ed0d31..bf16e5f 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -16,6 +16,30 @@ use Date; use format::{Item, Numeric, Pad, Fixed}; use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems}; +/// Specific formatting options for seconds +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum SecondsFormat { + /// Format whole seconds only, no subseconds. + Secs, + + /// Use fixed 3 subsecond digits. This corresponds to + /// [Fixed::Nanosecond3](format/enum.Fixed.html#variant.Nanosecond3) + Millis, + + /// Use fixed 6 subsecond digits. This corresponds to + /// [Fixed::Nanosecond6](format/enum.Fixed.html#variant.Nanosecond6) + Micros, + + /// Use fixed 9 subsecond digits. This corresponds to + /// [Fixed::Nanosecond9](format/enum.Fixed.html#variant.Nanosecond9) + Nanos, + + /// Use all available non-zero digits and thus any of above + /// formats. This corresponds to + /// [Fixed::Nanosecond](format/enum.Fixed.html#variant.Nanosecond) + Available, +} + /// ISO 8601 combined date and time with time zone. /// /// There are some constructors implemented here (the `from_*` methods), but @@ -246,43 +270,13 @@ impl DateTime where Tz::Offset: fmt::Display { self.format_with_items(ITEMS.iter().cloned()).to_string() } - /// Return an RFC 3339 and ISO 8601 date and time with subseconds formatted - /// as per a Fixed variant or None for no subseconds. The Fixed - /// variants supported are: Nanosecond, Nanosecond3, Nanosecond6 - /// and Nanosecond9. Other values will panic! - pub fn to_rfc3339p(&self, subform: Option) -> String { - self.rfc3339_via_items(subform, false) - } - - /// Return an RFC 3339 and ISO 8601 date and time with subseconds formatted - /// as per a Fixed variant or None for no subseconds. The Fixed - /// variants supported are: Nanosecond, Nanosecond3, Nanosecond6 - /// and Nanosecond9. Other values will panic! - /// If the timezone is UTC (offset 0), use 'Z'. - pub fn to_rfc3339pz(&self, subform: Option) -> String { - self.rfc3339_via_items(subform, true) - } - - /// Formats the combined date and time with the specified formatting items. - #[inline] - pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat - where I: Iterator> + Clone { - let local = self.naive_local(); - DelayedFormat::new_with_offset(Some(local.date()), Some(local.time()), &self.offset, items) - } - - /// Formats the combined date and time with the specified format string. - /// See the [`format::strftime` module](./format/strftime/index.html) - /// on the supported escape sequences. - #[inline] - pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat> { - self.format_with_items(StrftimeItems::new(fmt)) - } - - fn rfc3339_via_items(&self, subform: Option, use_z: bool) -> String - { + /// Return an RFC 3339 and ISO 8601 date and time with subseconds + /// formatted as per a `SecondsFormat`. If passed `use_z` true and the + /// timezone is UTC (offset 0), use 'Z'. + pub fn to_rfc3339_opts(&self, subform: SecondsFormat, use_z: bool) -> String { use format::Numeric::*; use format::Pad::Zero; + use SecondsFormat::*; const PREFIX: &'static [Item<'static>] = &[ Item::Numeric(Year, Zero), @@ -299,14 +293,11 @@ impl DateTime where Tz::Offset: fmt::Display { ]; let ssitem = match subform { - None => None, - Some(sf) => match sf { - Fixed::Nanosecond | - Fixed::Nanosecond3 | - Fixed::Nanosecond6 | - Fixed::Nanosecond9 => Some(Item::Fixed(sf)), - _ => panic!("Unsupported rfc_3339p subsecond format {:?}", sf) - } + Secs => None, + Millis => Some(Item::Fixed(Fixed::Nanosecond3)), + Micros => Some(Item::Fixed(Fixed::Nanosecond6)), + Nanos => Some(Item::Fixed(Fixed::Nanosecond9)), + Available => Some(Item::Fixed(Fixed::Nanosecond)), }; let tzitem = Item::Fixed( @@ -328,6 +319,22 @@ impl DateTime where Tz::Offset: fmt::Display { ).to_string(), } } + + /// Formats the combined date and time with the specified formatting items. + #[inline] + pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat + where I: Iterator> + Clone { + let local = self.naive_local(); + DelayedFormat::new_with_offset(Some(local.date()), Some(local.time()), &self.offset, items) + } + + /// Formats the combined date and time with the specified format string. + /// See the [`format::strftime` module](./format/strftime/index.html) + /// on the supported escape sequences. + #[inline] + pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat> { + self.format_with_items(StrftimeItems::new(fmt)) + } } impl Datelike for DateTime { @@ -1127,33 +1134,25 @@ mod tests { } #[test] - fn test_rfc3339p_and_z() { - use format::Fixed::*; - let pst = FixedOffset::east(8*60*60); - let dt = pst.ymd(2018, 1, 11).and_hms_nano(10, 5, 13, 84_660_684); - assert_eq!("2018-01-11T10:05:13+08:00", dt.to_rfc3339p (None)); - assert_eq!("2018-01-11T10:05:13+08:00", dt.to_rfc3339pz(None)); - assert_eq!("2018-01-11T10:05:13.084+08:00", dt.to_rfc3339p (Some(Nanosecond3))); - assert_eq!("2018-01-11T10:05:13.084660+08:00", dt.to_rfc3339p (Some(Nanosecond6))); - assert_eq!("2018-01-11T10:05:13.084660684+08:00", dt.to_rfc3339p (Some(Nanosecond9))); - assert_eq!("2018-01-11T10:05:13.084660684+08:00", dt.to_rfc3339p (Some(Nanosecond))); + fn test_rfc3339_opts() { + use SecondsFormat::*; + let pst = FixedOffset::east(8 * 60 * 60); + let dt = pst.ymd(2018, 1, 11).and_hms_nano(10, 5, 13, 084_660_684); + assert_eq!(dt.to_rfc3339_opts(Secs, false), "2018-01-11T10:05:13+08:00"); + assert_eq!(dt.to_rfc3339_opts(Secs, true), "2018-01-11T10:05:13+08:00"); + assert_eq!(dt.to_rfc3339_opts(Millis, false), "2018-01-11T10:05:13.084+08:00"); + assert_eq!(dt.to_rfc3339_opts(Micros, false), "2018-01-11T10:05:13.084660+08:00"); + assert_eq!(dt.to_rfc3339_opts(Nanos, false), "2018-01-11T10:05:13.084660684+08:00"); + assert_eq!(dt.to_rfc3339_opts(Available, false), "2018-01-11T10:05:13.084660684+08:00"); - let ut = DateTime::::from_utc( dt.naive_utc(), Utc ); - assert_eq!("2018-01-11T02:05:13+00:00", ut.to_rfc3339p (None)); - assert_eq!("2018-01-11T02:05:13Z", ut.to_rfc3339pz(None)); - assert_eq!("2018-01-11T02:05:13.084+00:00", ut.to_rfc3339p (Some(Nanosecond3))); - assert_eq!("2018-01-11T02:05:13.084Z", ut.to_rfc3339pz(Some(Nanosecond3))); - assert_eq!("2018-01-11T02:05:13.084660Z", ut.to_rfc3339pz(Some(Nanosecond6))); - assert_eq!("2018-01-11T02:05:13.084660684Z", ut.to_rfc3339pz(Some(Nanosecond9))); - assert_eq!("2018-01-11T02:05:13.084660684Z", ut.to_rfc3339pz(Some(Nanosecond))); - } - - #[test] - #[should_panic] - fn test_rfc3339p_fixed_bogus_n() { - use format::Fixed::*; - let now = Utc::now(); - println!("{}", now.to_rfc3339p(Some(UpperAmPm))); + let ut = DateTime::::from_utc(dt.naive_utc(), Utc); + assert_eq!(ut.to_rfc3339_opts(Secs, false), "2018-01-11T02:05:13+00:00"); + assert_eq!(ut.to_rfc3339_opts(Secs, true), "2018-01-11T02:05:13Z"); + assert_eq!(ut.to_rfc3339_opts(Millis, false), "2018-01-11T02:05:13.084+00:00"); + assert_eq!(ut.to_rfc3339_opts(Millis, true), "2018-01-11T02:05:13.084Z"); + assert_eq!(ut.to_rfc3339_opts(Micros, true), "2018-01-11T02:05:13.084660Z"); + assert_eq!(ut.to_rfc3339_opts(Nanos, true), "2018-01-11T02:05:13.084660684Z"); + assert_eq!(ut.to_rfc3339_opts(Available, true), "2018-01-11T02:05:13.084660684Z"); } #[test] diff --git a/src/lib.rs b/src/lib.rs index 4e37d30..5ced85a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -406,7 +406,7 @@ pub use oldtime::Duration; #[doc(no_inline)] pub use offset::{TimeZone, Offset, LocalResult, Utc, FixedOffset, Local}; #[doc(no_inline)] pub use naive::{NaiveDate, IsoWeek, NaiveTime, NaiveDateTime}; pub use date::{Date, MIN_DATE, MAX_DATE}; -pub use datetime::DateTime; +pub use datetime::{DateTime, SecondsFormat}; #[cfg(feature = "rustc-serialize")] pub use datetime::rustc_serialize::TsSeconds; pub use format::{ParseError, ParseResult}; @@ -417,7 +417,7 @@ pub mod prelude { #[doc(no_inline)] pub use {Utc, FixedOffset, Local}; #[doc(no_inline)] pub use {NaiveDate, NaiveTime, NaiveDateTime}; #[doc(no_inline)] pub use Date; - #[doc(no_inline)] pub use DateTime; + #[doc(no_inline)] pub use {DateTime, SecondsFormat}; } // useful throughout the codebase From e8fdbdf41d017b1811f2f82d793da175749039c4 Mon Sep 17 00:00:00 2001 From: David Kellum Date: Fri, 26 Jan 2018 11:35:19 -0800 Subject: [PATCH 6/6] Rustdoc and naming improvements --- src/datetime.rs | 86 +++++++++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 32 deletions(-) diff --git a/src/datetime.rs b/src/datetime.rs index bf16e5f..36fd160 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -16,28 +16,29 @@ use Date; use format::{Item, Numeric, Pad, Fixed}; use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems}; -/// Specific formatting options for seconds +/// Specific formatting options for seconds. This may be extended in the +/// future, so exhaustive matching in external code is not recommended. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum SecondsFormat { - /// Format whole seconds only, no subseconds. + /// Format whole seconds only, with no decimal point nor subseconds. Secs, /// Use fixed 3 subsecond digits. This corresponds to - /// [Fixed::Nanosecond3](format/enum.Fixed.html#variant.Nanosecond3) + /// [Fixed::Nanosecond3](format/enum.Fixed.html#variant.Nanosecond3). Millis, /// Use fixed 6 subsecond digits. This corresponds to - /// [Fixed::Nanosecond6](format/enum.Fixed.html#variant.Nanosecond6) + /// [Fixed::Nanosecond6](format/enum.Fixed.html#variant.Nanosecond6). Micros, /// Use fixed 9 subsecond digits. This corresponds to - /// [Fixed::Nanosecond9](format/enum.Fixed.html#variant.Nanosecond9) + /// [Fixed::Nanosecond9](format/enum.Fixed.html#variant.Nanosecond9). Nanos, - /// Use all available non-zero digits and thus any of above - /// formats. This corresponds to - /// [Fixed::Nanosecond](format/enum.Fixed.html#variant.Nanosecond) - Available, + /// Automatically select one of `Secs`, `Millis`, `Micros`, or `Nanos` to + /// display all available non-zero sub-second digits. This corresponds to + /// [Fixed::Nanosecond](format/enum.Fixed.html#variant.Nanosecond). + AutoSi, } /// ISO 8601 combined date and time with time zone. @@ -270,10 +271,31 @@ impl DateTime where Tz::Offset: fmt::Display { self.format_with_items(ITEMS.iter().cloned()).to_string() } - /// Return an RFC 3339 and ISO 8601 date and time with subseconds + /// Return an RFC 3339 and ISO 8601 date and time string with subseconds /// formatted as per a `SecondsFormat`. If passed `use_z` true and the - /// timezone is UTC (offset 0), use 'Z'. - pub fn to_rfc3339_opts(&self, subform: SecondsFormat, use_z: bool) -> String { + /// timezone is UTC (offset 0), use 'Z', as per + /// [Fixed::TimezoneOffsetColonZ](format/enum.Fixed.html#variant.TimezoneOffsetColonZ). + /// If passed `use_z` false, use + /// [Fixed::TimezoneOffsetColon](format/enum.Fixed.html#variant.TimezoneOffsetColon). + /// + /// # Examples + /// + /// ```rust + /// # use chrono::{DateTime, FixedOffset, SecondsFormat, TimeZone, Utc}; + /// let dt = Utc.ymd(2018, 1, 26).and_hms_micro(18, 30, 9, 453_829); + /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Millis, false), + /// "2018-01-26T18:30:09.453+00:00"); + /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Millis, true), + /// "2018-01-26T18:30:09.453Z"); + /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Secs, true), + /// "2018-01-26T18:30:09Z"); + /// + /// let pst = FixedOffset::east(8 * 60 * 60); + /// let dt = pst.ymd(2018, 1, 26).and_hms_micro(10, 30, 9, 453_829); + /// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Secs, true), + /// "2018-01-26T10:30:09+08:00"); + /// ``` + pub fn to_rfc3339_opts(&self, secform: SecondsFormat, use_z: bool) -> String { use format::Numeric::*; use format::Pad::Zero; use SecondsFormat::*; @@ -292,12 +314,12 @@ impl DateTime where Tz::Offset: fmt::Display { Item::Numeric(Second, Zero), ]; - let ssitem = match subform { - Secs => None, - Millis => Some(Item::Fixed(Fixed::Nanosecond3)), - Micros => Some(Item::Fixed(Fixed::Nanosecond6)), - Nanos => Some(Item::Fixed(Fixed::Nanosecond9)), - Available => Some(Item::Fixed(Fixed::Nanosecond)), + let ssitem = match secform { + Secs => None, + Millis => Some(Item::Fixed(Fixed::Nanosecond3)), + Micros => Some(Item::Fixed(Fixed::Nanosecond6)), + Nanos => Some(Item::Fixed(Fixed::Nanosecond9)), + AutoSi => Some(Item::Fixed(Fixed::Nanosecond)), }; let tzitem = Item::Fixed( @@ -1137,22 +1159,22 @@ mod tests { fn test_rfc3339_opts() { use SecondsFormat::*; let pst = FixedOffset::east(8 * 60 * 60); - let dt = pst.ymd(2018, 1, 11).and_hms_nano(10, 5, 13, 084_660_684); - assert_eq!(dt.to_rfc3339_opts(Secs, false), "2018-01-11T10:05:13+08:00"); - assert_eq!(dt.to_rfc3339_opts(Secs, true), "2018-01-11T10:05:13+08:00"); - assert_eq!(dt.to_rfc3339_opts(Millis, false), "2018-01-11T10:05:13.084+08:00"); - assert_eq!(dt.to_rfc3339_opts(Micros, false), "2018-01-11T10:05:13.084660+08:00"); - assert_eq!(dt.to_rfc3339_opts(Nanos, false), "2018-01-11T10:05:13.084660684+08:00"); - assert_eq!(dt.to_rfc3339_opts(Available, false), "2018-01-11T10:05:13.084660684+08:00"); + let dt = pst.ymd(2018, 1, 11).and_hms_nano(10, 5, 13, 084_660_000); + assert_eq!(dt.to_rfc3339_opts(Secs, false), "2018-01-11T10:05:13+08:00"); + assert_eq!(dt.to_rfc3339_opts(Secs, true), "2018-01-11T10:05:13+08:00"); + assert_eq!(dt.to_rfc3339_opts(Millis, false), "2018-01-11T10:05:13.084+08:00"); + assert_eq!(dt.to_rfc3339_opts(Micros, false), "2018-01-11T10:05:13.084660+08:00"); + assert_eq!(dt.to_rfc3339_opts(Nanos, false), "2018-01-11T10:05:13.084660000+08:00"); + assert_eq!(dt.to_rfc3339_opts(AutoSi, false), "2018-01-11T10:05:13.084660+08:00"); let ut = DateTime::::from_utc(dt.naive_utc(), Utc); - assert_eq!(ut.to_rfc3339_opts(Secs, false), "2018-01-11T02:05:13+00:00"); - assert_eq!(ut.to_rfc3339_opts(Secs, true), "2018-01-11T02:05:13Z"); - assert_eq!(ut.to_rfc3339_opts(Millis, false), "2018-01-11T02:05:13.084+00:00"); - assert_eq!(ut.to_rfc3339_opts(Millis, true), "2018-01-11T02:05:13.084Z"); - assert_eq!(ut.to_rfc3339_opts(Micros, true), "2018-01-11T02:05:13.084660Z"); - assert_eq!(ut.to_rfc3339_opts(Nanos, true), "2018-01-11T02:05:13.084660684Z"); - assert_eq!(ut.to_rfc3339_opts(Available, true), "2018-01-11T02:05:13.084660684Z"); + assert_eq!(ut.to_rfc3339_opts(Secs, false), "2018-01-11T02:05:13+00:00"); + assert_eq!(ut.to_rfc3339_opts(Secs, true), "2018-01-11T02:05:13Z"); + assert_eq!(ut.to_rfc3339_opts(Millis, false), "2018-01-11T02:05:13.084+00:00"); + assert_eq!(ut.to_rfc3339_opts(Millis, true), "2018-01-11T02:05:13.084Z"); + assert_eq!(ut.to_rfc3339_opts(Micros, true), "2018-01-11T02:05:13.084660Z"); + assert_eq!(ut.to_rfc3339_opts(Nanos, true), "2018-01-11T02:05:13.084660000Z"); + assert_eq!(ut.to_rfc3339_opts(AutoSi, true), "2018-01-11T02:05:13.084660Z"); } #[test]