From 62d289fc856f459adff3b828b227ccc5632f0525 Mon Sep 17 00:00:00 2001 From: Kang Seonghoon Date: Mon, 8 Aug 2016 03:04:39 +0900 Subject: [PATCH] Added documentations for `NaiveTime` and `NaiveDateTime` methods. Also slightly edited the `format` and `format_with_items` docs to be more unobstructive (i.e. implicit `use` from previous blocks). --- src/naive/date.rs | 31 ++++---- src/naive/datetime.rs | 169 +++++++++++++++++++++++++++++++++++++++++- src/naive/time.rs | 104 ++++++++++++++++++++++---- 3 files changed, 270 insertions(+), 34 deletions(-) diff --git a/src/naive/date.rs b/src/naive/date.rs index 6af4e7c..4aeaf19 100644 --- a/src/naive/date.rs +++ b/src/naive/date.rs @@ -850,18 +850,17 @@ impl NaiveDate { /// let fmt = StrftimeItems::new("%Y-%m-%d"); /// let d = NaiveDate::from_ymd(2015, 9, 5); /// assert_eq!(d.format_with_items(fmt.clone()).to_string(), "2015-09-05"); - /// assert_eq!(d.format("%Y-%m-%d").to_string(), "2015-09-05"); + /// assert_eq!(d.format("%Y-%m-%d").to_string(), "2015-09-05"); /// ~~~~ /// /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. /// /// ~~~~ - /// use chrono::NaiveDate; - /// use chrono::format::strftime::StrftimeItems; - /// - /// let fmt = StrftimeItems::new("%Y-%m-%d"); - /// let d = NaiveDate::from_ymd(2015, 9, 5); - /// assert_eq!(format!("{}", d.format_with_items(fmt.clone())), "2015-09-05"); + /// # use chrono::NaiveDate; + /// # use chrono::format::strftime::StrftimeItems; + /// # let fmt = StrftimeItems::new("%Y-%m-%d").clone(); + /// # let d = NaiveDate::from_ymd(2015, 9, 5); + /// assert_eq!(format!("{}", d.format_with_items(fmt)), "2015-09-05"); /// ~~~~ #[inline] pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat @@ -896,9 +895,8 @@ impl NaiveDate { /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. /// /// ~~~~ - /// use chrono::NaiveDate; - /// - /// let d = NaiveDate::from_ymd(2015, 9, 5); + /// # use chrono::NaiveDate; + /// # let d = NaiveDate::from_ymd(2015, 9, 5); /// 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"); /// ~~~~ @@ -1364,7 +1362,8 @@ impl Sub for NaiveDate { } } -/// The `Debug` output of the naive date `d` is same to `d.format("%Y-%m-%d")`. +/// The `Debug` output of the naive date `d` is same to +/// [`d.format("%Y-%m-%d")`](../../format/strftime/index.html). /// /// The string printed can be readily parsed via the `parse` method on `str`. /// @@ -1398,7 +1397,8 @@ impl fmt::Debug for NaiveDate { } } -/// The `Display` output of the naive date `d` is same to `d.format("%Y-%m-%d")`. +/// The `Display` output of the naive date `d` is same to +/// [`d.format("%Y-%m-%d")`](../../format/strftime/index.html). /// /// The string printed can be readily parsed via the `parse` method on `str`. /// @@ -1423,7 +1423,8 @@ impl fmt::Display for NaiveDate { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self, f) } } -/// Parsing a str into a `NaiveDate` uses the same format, `%Y-%m-%d`, as `Debug` and `Display`. +/// Parsing a `str` into a `NaiveDate` uses the same format, +/// [`%Y-%m-%d`](../../format/strftime/index.html), as in `Debug` and `Display`. /// /// # Example /// @@ -1431,10 +1432,10 @@ impl fmt::Display for NaiveDate { /// use chrono::NaiveDate; /// /// let d = NaiveDate::from_ymd(2015, 9, 18); -/// assert_eq!(format!("{}", d).parse::(), Ok(d)); +/// assert_eq!("2015-09-18".parse::(), Ok(d)); /// /// let d = NaiveDate::from_ymd(12345, 6, 7); -/// assert_eq!(format!("{}", d).parse::(), Ok(d)); +/// assert_eq!("+12345-6-7".parse::(), Ok(d)); /// /// assert!("foo".parse::().is_err()); /// ~~~~ diff --git a/src/naive/datetime.rs b/src/naive/datetime.rs index 254703e..593dc9b 100644 --- a/src/naive/datetime.rs +++ b/src/naive/datetime.rs @@ -25,28 +25,78 @@ pub struct NaiveDateTime { impl NaiveDateTime { /// Makes a new `NaiveDateTime` from date and time components. - /// Equivalent to `date.and_time(time)` and many other helper constructors on `NaiveDate`. + /// Equivalent to [`date.and_time(time)`](../date/struct.NaiveDate.html#method.and_time) + /// and many other helper constructors on `NaiveDate`. + /// + /// # Example + /// + /// ~~~~ + /// use chrono::{NaiveDate, NaiveTime, NaiveDateTime}; + /// + /// let d = NaiveDate::from_ymd(2015, 6, 3); + /// let t = NaiveTime::from_hms_milli(12, 34, 56, 789); + /// + /// let dt = NaiveDateTime::new(d, t); + /// assert_eq!(dt.date(), d); + /// assert_eq!(dt.time(), t); + /// ~~~~ #[inline] pub fn new(date: NaiveDate, time: NaiveTime) -> NaiveDateTime { NaiveDateTime { date: date, time: time } } - /// Makes a new `NaiveDateTime` from the number of non-leap seconds + /// Makes a new `NaiveDateTime` corresponding to a UTC date and time, + /// from the number of non-leap seconds /// since the midnight UTC on January 1, 1970 (aka "UNIX timestamp") /// and the number of nanoseconds since the last whole non-leap second. /// + /// The nanosecond part can exceed 1,000,000,000 + /// in order to represent the [leap second](../time/index.html#leap-second-handling). + /// (The true "UNIX timestamp" cannot represent a leap second unambiguously.) + /// /// Panics on the out-of-range number of seconds and/or invalid nanosecond. + /// + /// # Example + /// + /// ~~~~ + /// use chrono::{NaiveDateTime, NaiveDate}; + /// + /// let dt = NaiveDateTime::from_timestamp(0, 42_000_000); + /// assert_eq!(dt, NaiveDate::from_ymd(1970, 1, 1).and_hms_milli(0, 0, 0, 42)); + /// + /// let dt = NaiveDateTime::from_timestamp(1_000_000_000, 0); + /// assert_eq!(dt, NaiveDate::from_ymd(2001, 9, 9).and_hms(1, 46, 40)); + /// ~~~~ #[inline] pub fn from_timestamp(secs: i64, nsecs: u32) -> NaiveDateTime { let datetime = NaiveDateTime::from_timestamp_opt(secs, nsecs); datetime.expect("invalid or out-of-range datetime") } - /// Makes a new `NaiveDateTime` from the number of non-leap seconds + /// Makes a new `NaiveDateTime` corresponding to a UTC date and time, + /// from the number of non-leap seconds /// since the midnight UTC on January 1, 1970 (aka "UNIX timestamp") /// and the number of nanoseconds since the last whole non-leap second. /// + /// The nanosecond part can exceed 1,000,000,000 + /// in order to represent the [leap second](../time/index.html#leap-second-handling). + /// (The true "UNIX timestamp" cannot represent a leap second unambiguously.) + /// /// Returns `None` on the out-of-range number of seconds and/or invalid nanosecond. + /// + /// # Example + /// + /// ~~~~ + /// use chrono::{NaiveDateTime, NaiveDate}; + /// use std::i64; + /// + /// let from_timestamp_opt = NaiveDateTime::from_timestamp_opt; + /// assert!(from_timestamp_opt(0, 0).is_some()); + /// assert!(from_timestamp_opt(0, 999_999_999).is_some()); + /// assert!(from_timestamp_opt(0, 1_500_000_000).is_some()); // leap second + /// assert!(from_timestamp_opt(0, 2_000_000_000).is_none()); + /// assert!(from_timestamp_opt(i64::MAX, 0).is_none()); + /// ~~~~ #[inline] pub fn from_timestamp_opt(secs: i64, nsecs: u32) -> Option { let (days, secs) = div_mod_floor(secs, 86400); @@ -74,6 +124,64 @@ impl NaiveDateTime { /// Parses a string with the specified format string and returns a new `NaiveDateTime`. /// See the [`format::strftime` module](../../format/strftime/index.html) /// on the supported escape sequences. + /// + /// # Example + /// + /// ~~~~ + /// use chrono::{NaiveDateTime, NaiveDate}; + /// + /// let parse_from_str = NaiveDateTime::parse_from_str; + /// + /// assert_eq!(parse_from_str("2015-09-05 23:56:04", "%Y-%m-%d %H:%M:%S"), + /// Ok(NaiveDate::from_ymd(2015, 9, 5).and_hms(23, 56, 4))); + /// assert_eq!(parse_from_str("5sep2015pm012345.6789", "%d%b%Y%p%I%M%S%.f"), + /// Ok(NaiveDate::from_ymd(2015, 9, 5).and_hms_micro(13, 23, 45, 678_900))); + /// ~~~~ + /// + /// Offset is ignored for the purpose of parsing. + /// + /// ~~~~ + /// # use chrono::{NaiveDateTime, NaiveDate}; + /// # let parse_from_str = NaiveDateTime::parse_from_str; + /// assert_eq!(parse_from_str("2014-5-17T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"), + /// Ok(NaiveDate::from_ymd(2014, 5, 17).and_hms(12, 34, 56))); + /// ~~~~ + /// + /// [Leap seconds](./index.html#leap-second-handling) are correctly handled by + /// treating any time of the form `hh:mm:60` as a leap second. + /// (This equally applies to the formatting, so the round trip is possible.) + /// + /// ~~~~ + /// # use chrono::{NaiveDateTime, NaiveDate}; + /// # let parse_from_str = NaiveDateTime::parse_from_str; + /// assert_eq!(parse_from_str("2015-07-01 08:59:60.123", "%Y-%m-%d %H:%M:%S%.f"), + /// Ok(NaiveDate::from_ymd(2015, 7, 1).and_hms_milli(8, 59, 59, 1_123))); + /// ~~~~ + /// + /// Missing seconds are assumed to be zero, + /// but out-of-bound times or insufficient fields are errors otherwise. + /// + /// ~~~~ + /// # use chrono::{NaiveDateTime, NaiveDate}; + /// # let parse_from_str = NaiveDateTime::parse_from_str; + /// assert_eq!(parse_from_str("94/9/4 7:15", "%y/%m/%d %H:%M"), + /// Ok(NaiveDate::from_ymd(1994, 9, 4).and_hms(7, 15, 0))); + /// + /// assert!(parse_from_str("04m33s", "%Mm%Ss").is_err()); + /// assert!(parse_from_str("94/9/4 12", "%y/%m/%d %H").is_err()); + /// assert!(parse_from_str("94/9/4 17:60", "%y/%m/%d %H:%M").is_err()); + /// assert!(parse_from_str("94/9/4 24:00:00", "%y/%m/%d %H:%M:%S").is_err()); + /// ~~~~ + /// + /// All parsed fields should be consistent to each other, otherwise it's an error. + /// + /// ~~~~ + /// # use chrono::NaiveDateTime; + /// # let parse_from_str = NaiveDateTime::parse_from_str; + /// let fmt = "%Y-%m-%d %H:%M:%S = UNIX timestamp %s"; + /// assert!(parse_from_str("2001-09-09 01:46:39 = UNIX timestamp 999999999", fmt).is_ok()); + /// assert!(parse_from_str("1970-01-01 00:00:00 = UNIX timestamp 1", fmt).is_err()); + /// ~~~~ pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult { let mut parsed = Parsed::new(); try!(parse(&mut parsed, s, StrftimeItems::new(fmt))); @@ -181,6 +289,32 @@ impl NaiveDateTime { } /// Formats the combined date and time with the specified formatting items. + /// Otherwise it is same to the ordinary [`format`](#method.format) method. + /// + /// The `Iterator` of items should be `Clone`able, + /// since the resulting `DelayedFormat` value may be formatted multiple times. + /// + /// # Example + /// + /// ~~~~ + /// use chrono::NaiveDate; + /// use chrono::format::strftime::StrftimeItems; + /// + /// let fmt = StrftimeItems::new("%Y-%m-%d %H:%M:%S"); + /// let dt = NaiveDate::from_ymd(2015, 9, 5).and_hms(23, 56, 4); + /// assert_eq!(dt.format_with_items(fmt.clone()).to_string(), "2015-09-05 23:56:04"); + /// assert_eq!(dt.format("%Y-%m-%d %H:%M:%S").to_string(), "2015-09-05 23:56:04"); + /// ~~~~ + /// + /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. + /// + /// ~~~~ + /// # use chrono::NaiveDate; + /// # use chrono::format::strftime::StrftimeItems; + /// # let fmt = StrftimeItems::new("%Y-%m-%d %H:%M:%S").clone(); + /// # let dt = NaiveDate::from_ymd(2015, 9, 5).and_hms(23, 56, 4); + /// assert_eq!(format!("{}", dt.format_with_items(fmt)), "2015-09-05 23:56:04"); + /// ~~~~ #[inline] pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat where I: Iterator> + Clone { @@ -190,6 +324,35 @@ impl NaiveDateTime { /// 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. + /// + /// 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.) + /// + /// 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. + /// + /// # Example + /// + /// ~~~~ + /// use chrono::NaiveDate; + /// + /// let dt = NaiveDate::from_ymd(2015, 9, 5).and_hms(23, 56, 4); + /// assert_eq!(dt.format("%Y-%m-%d %H:%M:%S").to_string(), "2015-09-05 23:56:04"); + /// 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. + /// + /// ~~~~ + /// # use chrono::NaiveDate; + /// # let dt = NaiveDate::from_ymd(2015, 9, 5).and_hms(23, 56, 4); + /// 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"); + /// ~~~~ #[inline] pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat> { self.format_with_items(StrftimeItems::new(fmt)) diff --git a/src/naive/time.rs b/src/naive/time.rs index a1d648f..41e68d4 100644 --- a/src/naive/time.rs +++ b/src/naive/time.rs @@ -404,19 +404,17 @@ impl NaiveTime { /// let fmt = StrftimeItems::new("%H:%M:%S"); /// let t = NaiveTime::from_hms(23, 56, 4); /// assert_eq!(t.format_with_items(fmt.clone()).to_string(), "23:56:04"); - /// assert_eq!(t.format("%H:%M:%S").to_string(), "23:56:04"); + /// assert_eq!(t.format("%H:%M:%S").to_string(), "23:56:04"); /// ~~~~ /// /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. /// /// ~~~~ - /// use chrono::NaiveTime; - /// use chrono::format::strftime::StrftimeItems; - /// - /// let fmt = StrftimeItems::new("%H:%M:%S"); - /// let t = NaiveTime::from_hms(23, 56, 4); - /// assert_eq!(format!("{}", t.format_with_items(fmt.clone())), "23:56:04"); - /// assert_eq!(format!("{}", t.format("%H:%M:%S")), "23:56:04"); + /// # use chrono::NaiveTime; + /// # use chrono::format::strftime::StrftimeItems; + /// # let fmt = StrftimeItems::new("%H:%M:%S").clone(); + /// # let t = NaiveTime::from_hms(23, 56, 4); + /// assert_eq!(format!("{}", t.format_with_items(fmt)), "23:56:04"); /// ~~~~ #[inline] pub fn format_with_items<'a, I>(&self, items: I) -> DelayedFormat @@ -452,9 +450,8 @@ impl NaiveTime { /// The resulting `DelayedFormat` can be formatted directly via the `Display` trait. /// /// ~~~~ - /// use chrono::NaiveTime; - /// - /// let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); + /// # use chrono::NaiveTime; + /// # let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); /// 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"); @@ -941,11 +938,11 @@ impl Sub for NaiveTime { /// ~~~~ /// # use chrono::{NaiveTime, Duration}; /// # let hmsm = |h,m,s,milli| NaiveTime::from_hms_milli(h, m, s, milli); -/// assert_eq!(hmsm(3, 5, 59, 1_300) - Duration::zero(), hmsm(3, 5, 59, 1_300)); -/// assert_eq!(hmsm(3, 5, 59, 1_300) - Duration::milliseconds(200), hmsm(3, 5, 59, 1_100)); -/// assert_eq!(hmsm(3, 5, 59, 1_300) - Duration::milliseconds(500), hmsm(3, 5, 59, 800)); -/// assert_eq!(hmsm(3, 5, 59, 1_300) - Duration::seconds(60), hmsm(3, 5, 0, 300)); -/// assert_eq!(hmsm(3, 5, 59, 1_300) - Duration::days(1), hmsm(3, 6, 0, 300)); +/// assert_eq!(hmsm(3, 5, 59, 1_300) - Duration::zero(), hmsm(3, 5, 59, 1_300)); +/// assert_eq!(hmsm(3, 5, 59, 1_300) - Duration::milliseconds(200), hmsm(3, 5, 59, 1_100)); +/// assert_eq!(hmsm(3, 5, 59, 1_300) - Duration::milliseconds(500), hmsm(3, 5, 59, 800)); +/// assert_eq!(hmsm(3, 5, 59, 1_300) - Duration::seconds(60), hmsm(3, 5, 0, 300)); +/// assert_eq!(hmsm(3, 5, 59, 1_300) - Duration::days(1), hmsm(3, 6, 0, 300)); /// ~~~~ impl Sub for NaiveTime { type Output = NaiveTime; @@ -954,6 +951,34 @@ impl Sub for NaiveTime { fn sub(self, rhs: Duration) -> NaiveTime { self.add(-rhs) } } +/// The `Debug` output of the naive time `t` is same to +/// [`t.format("%H:%M:%S%.f")`](../../format/strftime/index.html). +/// +/// The string printed can be readily parsed via the `parse` method on `str`. +/// +/// It should be noted that, for leap seconds not on the minute boundary, +/// it may print a representation not distinguishable from non-leap seconds. +/// This doesn't matter in practice, since such leap seconds never happened. +/// (By the time of the first leap second on 1972-06-30, +/// every time zone offset around the world has standardized to the 5-minute alignment.) +/// +/// # Example +/// +/// ~~~~ +/// use chrono::NaiveTime; +/// +/// assert_eq!(format!("{:?}", NaiveTime::from_hms(23, 56, 4)), "23:56:04"); +/// assert_eq!(format!("{:?}", NaiveTime::from_hms_milli(23, 56, 4, 12)), "23:56:04.012"); +/// assert_eq!(format!("{:?}", NaiveTime::from_hms_micro(23, 56, 4, 1234)), "23:56:04.001234"); +/// assert_eq!(format!("{:?}", NaiveTime::from_hms_nano(23, 56, 4, 123456)), "23:56:04.000123456"); +/// ~~~~ +/// +/// Leap seconds may also be used. +/// +/// ~~~~ +/// # use chrono::NaiveTime; +/// assert_eq!(format!("{:?}", NaiveTime::from_hms_milli(6, 59, 59, 1_500)), "06:59:60.500"); +/// ~~~~ impl fmt::Debug for NaiveTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (hour, min, sec) = self.hms(); @@ -976,10 +1001,57 @@ impl fmt::Debug for NaiveTime { } } +/// The `Display` output of the naive time `t` is same to +/// [`t.format("%H:%M:%S%.f")`](../../format/strftime/index.html). +/// +/// The string printed can be readily parsed via the `parse` method on `str`. +/// +/// It should be noted that, for leap seconds not on the minute boundary, +/// it may print a representation not distinguishable from non-leap seconds. +/// This doesn't matter in practice, since such leap seconds never happened. +/// (By the time of the first leap second on 1972-06-30, +/// every time zone offset around the world has standardized to the 5-minute alignment.) +/// +/// # Example +/// +/// ~~~~ +/// use chrono::NaiveTime; +/// +/// assert_eq!(format!("{}", NaiveTime::from_hms(23, 56, 4)), "23:56:04"); +/// assert_eq!(format!("{}", NaiveTime::from_hms_milli(23, 56, 4, 12)), "23:56:04.012"); +/// assert_eq!(format!("{}", NaiveTime::from_hms_micro(23, 56, 4, 1234)), "23:56:04.001234"); +/// assert_eq!(format!("{}", NaiveTime::from_hms_nano(23, 56, 4, 123456)), "23:56:04.000123456"); +/// ~~~~ +/// +/// Leap seconds may also be used. +/// +/// ~~~~ +/// # use chrono::NaiveTime; +/// assert_eq!(format!("{}", NaiveTime::from_hms_milli(6, 59, 59, 1_500)), "06:59:60.500"); +/// ~~~~ impl fmt::Display for NaiveTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self, f) } } +/// Parsing a `str` into a `NaiveTime` uses the same format, +/// [`%H:%M:%S%.f`](../../format/strftime/index.html), as in `Debug` and `Display`. +/// +/// # Example +/// +/// ~~~~ +/// use chrono::NaiveTime; +/// +/// let t = NaiveTime::from_hms(23, 56, 4); +/// assert_eq!("23:56:04".parse::(), Ok(t)); +/// +/// let t = NaiveTime::from_hms_nano(23, 56, 4, 12_345_678); +/// assert_eq!("23:56:4.012345678".parse::(), Ok(t)); +/// +/// let t = NaiveTime::from_hms_nano(23, 59, 59, 1_234_567_890); // leap second +/// assert_eq!("23:59:60.23456789".parse::(), Ok(t)); +/// +/// assert!("foo".parse::().is_err()); +/// ~~~~ impl str::FromStr for NaiveTime { type Err = ParseError;