diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index 14ce537ab4..92c408a94b 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -765,17 +765,71 @@ where DelayedFormat::new_with_offset(Some(local.date()), Some(local.time()), &self.offset, items) } - /// Formats the combined date and time per the specified format string. + /// Formats the date and time with the specified format string. /// - /// See the [`crate::format::strftime`] module for the supported escape sequences. + /// See the [`format::strftime` module](crate::format::strftime) for the supported escape + /// sequences. + /// + /// This returns a `DelayedFormat`, which gets converted to a string only when actual formatting + /// happens. You can feed this into [`print!`] and other formatting macros. + /// (This can avoid a memory allocation.) + /// + /// If you want to format to a `String`, consider using the more direct method + /// [`format_to_string`](#method.format_to_string). + /// This is an alternative to calling [`ToString::to_string`] on the `DelayedFormat` returned by + /// this method. + /// + /// # Errors/panics + /// + /// This function does not panic or return an error. + /// + /// However the `Display` implementation of `DelayedFormat` can return an error if the format + /// string is invalid. Returning an error goes against the [contract for `Display`][1]. This + /// will be fixed in the next major version of chrono. + /// + /// Consumers of the `Display` trait, such as [`format!`], [`println!`] and [`to_string`] will + /// generally panic on an invalid formatting string. Consider using this function in combination + /// with formatting macro's that can pass on an error instead such as [`write!`] and + /// [`writeln!`]. + /// + /// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#formatting-traits + /// [`to_string`]: ToString::to_string + /// + /// # Errors + /// + /// This function does not panic or return an error. But the `Display` implementation can + /// return an error if the format string is invalid. + /// + /// If you need to handle a potentially invalid format string, use this function in combination + /// with formatting macro's that can pass on an error instead of panicking, such as [`write!`] + /// and [`writeln!`], instead of [`format!`] and [`println!`]. /// /// # Example - /// ```rust - /// use chrono::prelude::*; /// - /// let date_time: DateTime = Utc.with_ymd_and_hms(2017, 04, 02, 12, 50, 32).unwrap(); - /// let formatted = format!("{}", date_time.format("%d/%m/%Y %H:%M")); - /// assert_eq!(formatted, "02/04/2017 12:50"); + /// ``` + /// use chrono::{TimeZone, Utc}; + /// + /// let dt = Utc.with_ymd_and_hms(2015, 9, 5, 23, 56, 4).unwrap(); + /// assert_eq!(dt.format("%Y-%m-%d %H:%M:%S %Z").to_string(), "2015-09-05 23:56:04 UTC"); + /// assert_eq!(dt.format("%Y-%m-%d %H:%M:%S %:z").to_string(), "2015-09-05 23:56:04 +00:00"); + /// assert_eq!( dt.format("around %l %p on %b %-d").to_string(), "around 11 PM on Sep 5"); + /// ``` + /// + /// The resulting `DelayedFormat` can be used directly with formatting macro's via the `Display` + /// trait. + /// + /// ``` + /// # use core::fmt::{Error, Write}; + /// # use chrono::{TimeZone, Utc}; + /// # let dt = Utc.with_ymd_and_hms(2015, 9, 5, 23, 56, 4).unwrap(); + /// assert_eq!(format!("{}", dt.format("%Y-%m-%d %H:%M:%S %Z")), "2015-09-05 23:56:04 UTC"); + /// + /// let mut formatted = String::new(); + /// write!(formatted, "{}", dt.format("around %l %p on %b %-d"))?; + /// assert_eq!(formatted, "around 11 PM on Sep 5"); + /// + /// println!("{}", dt.format("%Y-%m-%d %H:%M:%S %:z")); // prints "2015-09-05 23:56:04 +00:00" + /// # Ok::<(), Error>(()) /// ``` #[cfg(any(feature = "alloc", feature = "std", test))] #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))] @@ -785,6 +839,42 @@ where self.format_with_items(StrftimeItems::new(fmt)) } + /// Format the date and time with the specified format string directly to a `String`. + /// + /// See the [`format::strftime` module](crate::format::strftime) for the supported escape + /// sequences. + /// + /// # Errors + /// + /// Returns an error if the format string is invalid. + /// + /// # Example + /// + /// ``` + /// use chrono::{TimeZone, Utc}; + /// + /// let dt = Utc.with_ymd_and_hms(2015, 9, 5, 23, 56, 4).unwrap(); + /// assert_eq!( + /// dt.format_to_string("%Y-%m-%d %H:%M:%S %Z"), + /// Ok("2015-09-05 23:56:04 UTC".to_owned()) + /// ); + /// assert_eq!( + /// dt.format_to_string("%Y-%m-%d %H:%M:%S %:z"), + /// Ok("2015-09-05 23:56:04 +00:00".to_owned()) + /// ); + /// assert_eq!( + /// dt.format_to_string("around %l %p on %b %-d"), + /// Ok("around 11 PM on Sep 5".to_owned()) + /// ); + /// ``` + #[cfg(any(feature = "alloc", feature = "std", test))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))] + pub fn format_to_string(&self, fmt: &str) -> Result { + let mut s = String::new(); + write!(s, "{}", self.format_with_items(StrftimeItems::new(fmt)))?; + Ok(s) + } + /// Formats the combined date and time with the specified formatting items and locale. #[cfg(feature = "unstable-locales")] #[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))] diff --git a/src/datetime/tests.rs b/src/datetime/tests.rs index 7b3c164406..8a3c833ba5 100644 --- a/src/datetime/tests.rs +++ b/src/datetime/tests.rs @@ -1022,3 +1022,9 @@ fn test_datetime_fixed_offset() { let datetime_fixed = fixed_offset.from_local_datetime(&naivedatetime).unwrap(); assert_eq!(datetime_fixed.fixed_offset(), datetime_fixed); } + +#[test] +fn test_formatting_permissive_offset_no_panic() { + let dt = Utc.with_ymd_and_hms(2014, 11, 28, 12, 0, 9).unwrap(); + assert!(dt.format_to_string("%#z").is_err()); +} diff --git a/src/format/mod.rs b/src/format/mod.rs index 93c9f86d09..48a7925d20 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -675,7 +675,7 @@ fn format_inner( off.map(|&(_, off)| write_local_minus_utc(result, off, true, Colons::None)) } Internal(InternalFixed { val: InternalInternal::TimezoneOffsetPermissive }) => { - panic!("Do not try to write %#z it is undefined") + None // Do not try to write %#z it is undefined } RFC2822 => // same as `%a, %d %b %Y %H:%M:%S %z` diff --git a/src/lib.rs b/src/lib.rs index 3737d1a9b2..ecb75660e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -204,7 +204,8 @@ //! //! ### Formatting and Parsing //! -//! Formatting is done via the [`format`](./struct.DateTime.html#method.format) method, +//! Formatting is done via the [`format`](./struct.DateTime.html#method.format) and +//! [`format_to_string`](./struct.DateTime.html#method.format_to_string) methods, //! which format is equivalent to the familiar `strftime` format. //! //! See [`format::strftime`](./format/strftime/index.html#specifiers) @@ -233,8 +234,11 @@ //! # fn test() { //! let dt = Utc.with_ymd_and_hms(2014, 11, 28, 12, 0, 9).unwrap(); //! assert_eq!(dt.format("%Y-%m-%d %H:%M:%S").to_string(), "2014-11-28 12:00:09"); -//! assert_eq!(dt.format("%a %b %e %T %Y").to_string(), "Fri Nov 28 12:00:09 2014"); -//! assert_eq!(dt.format_localized("%A %e %B %Y, %T", Locale::fr_BE).to_string(), "vendredi 28 novembre 2014, 12:00:09"); +//! assert_eq!(dt.format_to_string("%a %b %e %T %Y"), Ok("Fri Nov 28 12:00:09 2014".to_owned())); +//! assert_eq!( +//! dt.format_localized("%A %e %B %Y, %T", Locale::fr_BE).to_string(), +//! "vendredi 28 novembre 2014, 12:00:09" +//! ); //! //! assert_eq!(dt.format("%a %b %e %T %Y").to_string(), dt.format("%c").to_string()); //! assert_eq!(dt.to_string(), "2014-11-28 12:00:09 UTC"); diff --git a/src/naive/date.rs b/src/naive/date.rs index b9404a15f5..70565be7e7 100644 --- a/src/naive/date.rs +++ b/src/naive/date.rs @@ -3,8 +3,14 @@ //! ISO 8601 calendar date without timezone. +#[cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use alloc::string::String; #[cfg(any(feature = "alloc", feature = "std", test))] use core::borrow::Borrow; +use core::fmt::Write; use core::ops::{Add, AddAssign, RangeInclusive, Sub, SubAssign}; use core::{fmt, str}; @@ -1210,18 +1216,35 @@ impl NaiveDate { } /// Formats the date with the specified format string. - /// See the [`format::strftime` module](../format/strftime/index.html) - /// on the supported escape sequences. /// - /// This returns a `DelayedFormat`, - /// which gets converted to a string only when actual formatting happens. - /// You may use the `to_string` method to get a `String`, - /// or just feed it into `print!` and other formatting macros. - /// (In this way it avoids the redundant memory allocation.) + /// See the [`format::strftime` module](crate::format::strftime) for the supported escape + /// sequences. + /// + /// This returns a `DelayedFormat`, which gets converted to a string only when actual formatting + /// happens. You can feed this into [`print!`] and other formatting macros. + /// (This can avoid a memory allocation.) + /// + /// If you want to format to a `String`, consider using the more direct method + /// [`format_to_string`](#method.format_to_string). + /// This is an alternative to calling [`ToString::to_string`] on the `DelayedFormat` returned by + /// this method. + /// + /// # Errors/panics + /// + /// This function does not panic or return an error. /// - /// A wrong format string does *not* issue an error immediately. - /// Rather, converting or formatting the `DelayedFormat` fails. - /// You are recommended to immediately use `DelayedFormat` for this reason. + /// However the `Display` implementation of `DelayedFormat` can return an error if the format + /// string is invalid, or if the format string contains time or offset fields (which a + /// `NaiveDate` can not provide). Returning an error goes against the + /// [contract for `Display`][1]. This will be fixed in the next major version of chrono. + /// + /// Consumers of the `Display` trait, such as [`format!`], [`println!`] and [`to_string`] will + /// generally panic on an invalid formatting string. Consider using this function in combination + /// with formatting macro's that can pass on an error instead such as [`write!`] and + /// [`writeln!`]. + /// + /// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#formatting-traits + /// [`to_string`]: ToString::to_string /// /// # Example /// @@ -1233,13 +1256,21 @@ impl NaiveDate { /// assert_eq!(d.format("%A, %-d %B, %C%y").to_string(), "Saturday, 5 September, 2015"); /// ``` /// - /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. + /// The resulting `DelayedFormat` can be used directly with formatting macro's via the `Display` + /// trait. /// /// ``` + /// # use core::fmt::{Error, Write}; /// # use chrono::NaiveDate; /// # let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap(); /// assert_eq!(format!("{}", d.format("%Y-%m-%d")), "2015-09-05"); - /// assert_eq!(format!("{}", d.format("%A, %-d %B, %C%y")), "Saturday, 5 September, 2015"); + /// + /// let mut formatted = String::new(); + /// write!(formatted, "{}", d.format("%A, %-d %B, %C%y"))?; + /// assert_eq!(formatted, "Saturday, 5 September, 2015"); + /// + /// println!("{}", d.format("%Y-%m-%d")); // prints "2015-09-05" + /// # Ok::<(), Error>(()) /// ``` #[cfg(any(feature = "alloc", feature = "std", test))] #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))] @@ -1249,6 +1280,36 @@ impl NaiveDate { self.format_with_items(StrftimeItems::new(fmt)) } + /// Format the date with the specified format string directly to a `String`. + /// + /// See the [`format::strftime` module](crate::format::strftime) for the supported escape + /// sequences. + /// + /// # Errors + /// + /// Returns an error if the format string is invalid, or if the format string contains time or + /// offset fields (which a `NaiveDate` can not provide). + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDate; + /// + /// let d = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap(); + /// assert_eq!(d.format_to_string("%Y-%m-%d"), Ok("2015-09-05".to_owned())); + /// assert_eq!( + /// d.format_to_string("%A, %-d %B, %C%y"), + /// Ok("Saturday, 5 September, 2015".to_owned()) + /// ); + /// ``` + #[cfg(any(feature = "alloc", feature = "std", test))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))] + pub fn format_to_string(&self, fmt: &str) -> Result { + let mut s = String::new(); + write!(s, "{}", self.format_with_items(StrftimeItems::new(fmt)))?; + Ok(s) + } + /// Formats the date with the specified formatting items and locale. #[cfg(feature = "unstable-locales")] #[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))] @@ -1992,8 +2053,6 @@ impl DoubleEndedIterator for NaiveDateWeeksIterator { /// ``` impl fmt::Debug for NaiveDate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use core::fmt::Write; - let year = self.year(); let mdf = self.mdf(); if (0..=9999).contains(&year) { diff --git a/src/naive/datetime/mod.rs b/src/naive/datetime/mod.rs index d32a388e5d..c744277517 100644 --- a/src/naive/datetime/mod.rs +++ b/src/naive/datetime/mod.rs @@ -3,6 +3,11 @@ //! ISO 8601 date and time without timezone. +#[cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use alloc::string::String; #[cfg(any(feature = "alloc", feature = "std", test))] use core::borrow::Borrow; use core::fmt::Write; @@ -858,19 +863,36 @@ impl NaiveDateTime { DelayedFormat::new(Some(self.date), Some(self.time), 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. + /// Formats the date and time with the specified format string. + /// + /// See the [`format::strftime` module](crate::format::strftime) for the supported escape + /// sequences. + /// + /// This returns a `DelayedFormat`, which gets converted to a string only when actual formatting + /// happens. You can feed this into [`print!`] and other formatting macros. + /// (This can avoid a memory allocation.) + /// + /// If you want to format to a `String`, consider using the more direct method + /// [`format_to_string`](#method.format_to_string). + /// This is an alternative to calling [`ToString::to_string`] on the `DelayedFormat` returned by + /// this method. + /// + /// # Errors/panics + /// + /// This function does not panic or return an error. /// - /// This returns a `DelayedFormat`, - /// which gets converted to a string only when actual formatting happens. - /// You may use the `to_string` method to get a `String`, - /// or just feed it into `print!` and other formatting macros. - /// (In this way it avoids the redundant memory allocation.) + /// However the `Display` implementation of `DelayedFormat` can return an error if the format + /// string is invalid, or if the format string contains offset fields (which a `NaiveDateTime` + /// can not provide). Returning an error goes against the [contract for `Display`][1]. This will + /// be fixed in the next major version of chrono. /// - /// A wrong format string does *not* issue an error immediately. - /// Rather, converting or formatting the `DelayedFormat` fails. - /// You are recommended to immediately use `DelayedFormat` for this reason. + /// Consumers of the `Display` trait, such as [`format!`], [`println!`] and [`to_string`] will + /// generally panic on an invalid formatting string. Consider using this function in combination + /// with formatting macro's that can pass on an error instead such as [`write!`] and + /// [`writeln!`]. + /// + /// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#formatting-traits + /// [`to_string`]: ToString::to_string /// /// # Example /// @@ -882,13 +904,21 @@ impl NaiveDateTime { /// assert_eq!(dt.format("around %l %p on %b %-d").to_string(), "around 11 PM on Sep 5"); /// ``` /// - /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. + /// The resulting `DelayedFormat` can be used directly with formatting macro's via the `Display` + /// trait. /// /// ``` + /// # use core::fmt::{Error, Write}; /// # use chrono::NaiveDate; /// # let dt = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().and_hms_opt(23, 56, 4).unwrap(); /// assert_eq!(format!("{}", dt.format("%Y-%m-%d %H:%M:%S")), "2015-09-05 23:56:04"); - /// assert_eq!(format!("{}", dt.format("around %l %p on %b %-d")), "around 11 PM on Sep 5"); + /// + /// let mut formatted = String::new(); + /// write!(formatted, "{}", dt.format("around %l %p on %b %-d"))?; + /// assert_eq!(formatted, "around 11 PM on Sep 5"); + /// + /// println!("{}", dt.format("%Y-%m-%d %H:%M:%S")); // prints "2015-09-05 23:56:04" + /// # Ok::<(), Error>(()) /// ``` #[cfg(any(feature = "alloc", feature = "std", test))] #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))] @@ -898,6 +928,36 @@ impl NaiveDateTime { self.format_with_items(StrftimeItems::new(fmt)) } + /// Format the date and time with the specified format string directly to a `String`. + /// + /// See the [`format::strftime` module](crate::format::strftime) for the supported escape + /// sequences. + /// + /// # Errors + /// + /// Returns an error if the format string is invalid, or if the format string contains offset + /// fields (which a `NaiveDateTime` can not provide). + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveDate; + /// + /// let dt = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().and_hms_opt(23, 56, 4).unwrap(); + /// assert_eq!(dt.format_to_string("%Y-%m-%d %H:%M:%S"), Ok("2015-09-05 23:56:04".to_owned())); + /// assert_eq!( + /// dt.format_to_string("around %l %p on %b %-d"), + /// Ok("around 11 PM on Sep 5".to_owned()) + /// ); + /// ``` + #[cfg(any(feature = "alloc", feature = "std", test))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))] + pub fn format_to_string(&self, fmt: &str) -> Result { + let mut s = String::new(); + write!(s, "{}", self.format_with_items(StrftimeItems::new(fmt)))?; + Ok(s) + } + /// Converts the `NaiveDateTime` into the timezone-aware `DateTime` /// with the provided timezone, if possible. /// diff --git a/src/naive/time/mod.rs b/src/naive/time/mod.rs index 3700c5cba2..7ba645ebbe 100644 --- a/src/naive/time/mod.rs +++ b/src/naive/time/mod.rs @@ -3,8 +3,14 @@ //! ISO 8601 time without timezone. +#[cfg(feature = "alloc")] +extern crate alloc; + +#[cfg(all(not(feature = "std"), feature = "alloc"))] +use alloc::string::String; #[cfg(any(feature = "alloc", feature = "std", test))] use core::borrow::Borrow; +use core::fmt::Write; use core::ops::{Add, AddAssign, Sub, SubAssign}; use core::{fmt, str}; @@ -742,18 +748,35 @@ impl NaiveTime { } /// Formats the time with the specified format string. - /// See the [`format::strftime` module](../format/strftime/index.html) - /// on the supported escape sequences. /// - /// This returns a `DelayedFormat`, - /// which gets converted to a string only when actual formatting happens. - /// You may use the `to_string` method to get a `String`, - /// or just feed it into `print!` and other formatting macros. - /// (In this way it avoids the redundant memory allocation.) + /// See the [`format::strftime` module](crate::format::strftime) for the supported escape + /// sequences. + /// + /// This returns a `DelayedFormat`, which gets converted to a string only when actual formatting + /// happens. You can feed this into [`print!`] and other formatting macros. + /// (This can avoid a memory allocation.) + /// + /// If you want to format to a `String`, consider using the more direct method + /// [`format_to_string`](#method.format_to_string). + /// This is an alternative to calling [`ToString::to_string`] on the `DelayedFormat` returned by + /// this method. + /// + /// # Errors/panics + /// + /// This function does not panic or return an error. /// - /// A wrong format string does *not* issue an error immediately. - /// Rather, converting or formatting the `DelayedFormat` fails. - /// You are recommended to immediately use `DelayedFormat` for this reason. + /// However the `Display` implementation of `DelayedFormat` can return an error if the format + /// string is invalid, or if the format string contains date or offset fields (which a + /// `NaiveTime` can not provide). Returning an error goes against the + /// [contract for `Display`][1]. This will be fixed in the next major version of chrono. + /// + /// Consumers of the `Display` trait, such as [`format!`], [`println!`] and [`to_string`] will + /// generally panic on an invalid formatting string. Consider using this function in combination + /// with formatting macro's that can pass on an error instead such as [`write!`] and + /// [`writeln!`]. + /// + /// [1]: https://doc.rust-lang.org/stable/std/fmt/index.html#formatting-traits + /// [`to_string`]: ToString::to_string /// /// # Example /// @@ -766,14 +789,21 @@ impl NaiveTime { /// assert_eq!(t.format("%-I:%M %p").to_string(), "11:56 PM"); /// ``` /// - /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. + /// The resulting `DelayedFormat` can be used directly with formatting macro's via the `Display` + /// trait. /// /// ``` + /// # use core::fmt::{Error, Write}; /// # use chrono::NaiveTime; /// # let t = NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap(); /// assert_eq!(format!("{}", t.format("%H:%M:%S")), "23:56:04"); - /// assert_eq!(format!("{}", t.format("%H:%M:%S%.6f")), "23:56:04.012345"); - /// assert_eq!(format!("{}", t.format("%-I:%M %p")), "11:56 PM"); + /// + /// let mut formatted = String::new(); + /// write!(formatted, "{}", t.format("%H:%M:%S%.6f"))?; + /// assert_eq!(formatted, "23:56:04.012345"); + /// + /// println!("{}", t.format("%-I:%M %p")); // prints "11:56 PM" + /// # Ok::<(), Error>(()) /// ``` #[cfg(any(feature = "alloc", feature = "std", test))] #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))] @@ -783,6 +813,34 @@ impl NaiveTime { self.format_with_items(StrftimeItems::new(fmt)) } + /// Format the time with the specified format string directly to a `String`. + /// + /// See the [`format::strftime` module](crate::format::strftime) for the supported escape + /// sequences. + /// + /// # Errors + /// + /// Returns an error if the format string is invalid, or if the format string contains date or + /// offset fields (which a `NaiveTime` can not provide). + /// + /// # Example + /// + /// ``` + /// use chrono::NaiveTime; + /// + /// let t = NaiveTime::from_hms_nano_opt(23, 56, 4, 12_345_678).unwrap(); + /// assert_eq!(t.format_to_string("%H:%M:%S"), Ok("23:56:04".to_owned())); + /// assert_eq!(t.format_to_string("%H:%M:%S%.6f"), Ok("23:56:04.012345".to_owned())); + /// assert_eq!(t.format_to_string("%-I:%M %p"), Ok("11:56 PM".to_owned())); + /// ``` + #[cfg(any(feature = "alloc", feature = "std", test))] + #[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))] + pub fn format_to_string(&self, fmt: &str) -> Result { + let mut s = String::new(); + write!(s, "{}", self.format_with_items(StrftimeItems::new(fmt)))?; + Ok(s) + } + /// Returns a triple of the hour, minute and second numbers. fn hms(&self) -> (u32, u32, u32) { let sec = self.secs % 60; @@ -1227,7 +1285,6 @@ impl fmt::Debug for NaiveTime { (sec, self.frac) }; - use core::fmt::Write; write_hundreds(f, hour as u8)?; f.write_char(':')?; write_hundreds(f, min as u8)?;