Incremental doc updates for `NaiveDateTime`.

Also moved the leap second arithmetic examples to
`chrono::naive::time`, as it became hard to link from other pages.
This commit is contained in:
Kang Seonghoon 2016-08-16 02:13:43 +09:00
parent 0393cae36d
commit 8b382fca45
No known key found for this signature in database
GPG Key ID: 82440FABA6709020
2 changed files with 194 additions and 47 deletions

View File

@ -17,6 +17,30 @@ use format::{Item, Numeric, Pad, Fixed};
use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems}; use format::{parse, Parsed, ParseError, ParseResult, DelayedFormat, StrftimeItems};
/// ISO 8601 combined date and time without timezone. /// ISO 8601 combined date and time without timezone.
///
/// # Example
///
/// `NaiveDateTime` is commonly created from [`NaiveDate`](../date/struct.NaiveDate.html).
///
/// ~~~~
/// use chrono::{NaiveDate, NaiveDateTime};
///
/// let dt: NaiveDateTime = NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11);
/// # let _ = dt;
/// ~~~~
///
/// You can use typical [date-like](../../trait.Datelike.html) and
/// [time-like](../../trait.Timelike.html) methods,
/// provided that relevant traits are in the scope.
///
/// ~~~~
/// # use chrono::{NaiveDate, NaiveDateTime};
/// # let dt: NaiveDateTime = NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11);
/// use chrono::{Datelike, Timelike, Weekday};
///
/// assert_eq!(dt.weekday(), Weekday::Fri);
/// assert_eq!(dt.num_seconds_from_midnight(), 33011);
/// ~~~~
#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
pub struct NaiveDateTime { pub struct NaiveDateTime {
date: NaiveDate, date: NaiveDate,
@ -190,12 +214,30 @@ impl NaiveDateTime {
} }
/// Retrieves a date component. /// Retrieves a date component.
///
/// # Example
///
/// ~~~~
/// use chrono::NaiveDate;
///
/// let dt = NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11);
/// assert_eq!(dt.date(), NaiveDate::from_ymd(2016, 7, 8));
/// ~~~~
#[inline] #[inline]
pub fn date(&self) -> NaiveDate { pub fn date(&self) -> NaiveDate {
self.date self.date
} }
/// Retrieves a time component. /// Retrieves a time component.
///
/// # Example
///
/// ~~~~
/// use chrono::{NaiveDate, NaiveTime};
///
/// let dt = NaiveDate::from_ymd(2016, 7, 8).and_hms(9, 10, 11);
/// assert_eq!(dt.time(), NaiveTime::from_hms(9, 10, 11));
/// ~~~~
#[inline] #[inline]
pub fn time(&self) -> NaiveTime { pub fn time(&self) -> NaiveTime {
self.time self.time
@ -205,6 +247,18 @@ impl NaiveDateTime {
/// ///
/// Note that this does *not* account for the timezone! /// Note that this does *not* account for the timezone!
/// The true "UNIX timestamp" would count seconds since the midnight *UTC* on the epoch. /// The true "UNIX timestamp" would count seconds since the midnight *UTC* on the epoch.
///
/// # Example
///
/// ~~~~
/// use chrono::NaiveDate;
///
/// let dt = NaiveDate::from_ymd(1970, 1, 1).and_hms_milli(0, 0, 1, 980);
/// assert_eq!(dt.timestamp(), 1);
///
/// let dt = NaiveDate::from_ymd(2001, 9, 9).and_hms(1, 46, 40);
/// assert_eq!(dt.timestamp(), 1_000_000_000);
/// ~~~~
#[inline] #[inline]
pub fn timestamp(&self) -> i64 { pub fn timestamp(&self) -> i64 {
let ndays = self.date.num_days_from_ce() as i64; let ndays = self.date.num_days_from_ce() as i64;
@ -216,6 +270,18 @@ impl NaiveDateTime {
/// ///
/// The return value ranges from 0 to 999, /// The return value ranges from 0 to 999,
/// or for [leap seconds](../time/index.html#leap-second-handling), to 1,999. /// or for [leap seconds](../time/index.html#leap-second-handling), to 1,999.
///
/// # Example
///
/// ~~~~
/// use chrono::NaiveDate;
///
/// let dt = NaiveDate::from_ymd(2016, 7, 8).and_hms_nano(9, 10, 11, 123_456_789);
/// assert_eq!(dt.timestamp_subsec_millis(), 123);
///
/// let dt = NaiveDate::from_ymd(2015, 7, 1).and_hms_nano(8, 59, 59, 1_234_567_890);
/// assert_eq!(dt.timestamp_subsec_millis(), 1_234);
/// ~~~~
#[inline] #[inline]
pub fn timestamp_subsec_millis(&self) -> u32 { pub fn timestamp_subsec_millis(&self) -> u32 {
self.timestamp_subsec_nanos() / 1_000_000 self.timestamp_subsec_nanos() / 1_000_000
@ -225,6 +291,18 @@ impl NaiveDateTime {
/// ///
/// The return value ranges from 0 to 999,999, /// The return value ranges from 0 to 999,999,
/// or for [leap seconds](../time/index.html#leap-second-handling), to 1,999,999. /// or for [leap seconds](../time/index.html#leap-second-handling), to 1,999,999.
///
/// # Example
///
/// ~~~~
/// use chrono::NaiveDate;
///
/// let dt = NaiveDate::from_ymd(2016, 7, 8).and_hms_nano(9, 10, 11, 123_456_789);
/// assert_eq!(dt.timestamp_subsec_micros(), 123_456);
///
/// let dt = NaiveDate::from_ymd(2015, 7, 1).and_hms_nano(8, 59, 59, 1_234_567_890);
/// assert_eq!(dt.timestamp_subsec_micros(), 1_234_567);
/// ~~~~
#[inline] #[inline]
pub fn timestamp_subsec_micros(&self) -> u32 { pub fn timestamp_subsec_micros(&self) -> u32 {
self.timestamp_subsec_nanos() / 1_000 self.timestamp_subsec_nanos() / 1_000
@ -234,6 +312,18 @@ impl NaiveDateTime {
/// ///
/// The return value ranges from 0 to 999,999,999, /// The return value ranges from 0 to 999,999,999,
/// or for [leap seconds](../time/index.html#leap-second-handling), to 1,999,999,999. /// or for [leap seconds](../time/index.html#leap-second-handling), to 1,999,999,999.
///
/// # Example
///
/// ~~~~
/// use chrono::NaiveDate;
///
/// let dt = NaiveDate::from_ymd(2016, 7, 8).and_hms_nano(9, 10, 11, 123_456_789);
/// assert_eq!(dt.timestamp_subsec_nanos(), 123_456_789);
///
/// let dt = NaiveDate::from_ymd(2015, 7, 1).and_hms_nano(8, 59, 59, 1_234_567_890);
/// assert_eq!(dt.timestamp_subsec_nanos(), 1_234_567_890);
/// ~~~~
#[inline] #[inline]
pub fn timestamp_subsec_nanos(&self) -> u32 { pub fn timestamp_subsec_nanos(&self) -> u32 {
self.time.nanosecond() self.time.nanosecond()

View File

@ -29,18 +29,115 @@
//! //!
//! Chrono does not try to accurately implement leap seconds; it is impossible. //! Chrono does not try to accurately implement leap seconds; it is impossible.
//! Rather, **it allows for leap seconds but behaves as if there are *no other* leap seconds.** //! Rather, **it allows for leap seconds but behaves as if there are *no other* leap seconds.**
//! Various time arithmetics will ignore any possible leap second(s) //! Various operations will ignore any possible leap second(s)
//! except when the operand were actually a leap second. //! except when any of the operands were actually leap seconds.
//! The leap second is indicated via fractional seconds more than 1 second,
//! so values like `NaiveTime::from_hms_milli(23, 56, 4, 1_005)` are allowed;
//! that value would mean 5ms after the beginning of a leap second following 23:56:04.
//! Parsing and formatting will correctly handle times that look like leap seconds,
//! and you can then conveniently ignore leap seconds if you are not prepared for them.
//! //!
//! If you cannot tolerate this behavior, //! If you cannot tolerate this behavior,
//! you must use a separate `TimeZone` for the International Atomic Time (TAI). //! you must use a separate `TimeZone` for the International Atomic Time (TAI).
//! TAI is like UTC but has no leap seconds, and thus slightly differs from UTC. //! TAI is like UTC but has no leap seconds, and thus slightly differs from UTC.
//! Chrono 0.2 does not provide such implementation, but it is planned for 0.3. //! Chrono 0.2 does not provide such implementation, but it is planned for 0.3.
//!
//! ## Representing Leap Seconds
//!
//! The leap second is indicated via fractional seconds more than 1 second.
//! This makes possible to treat a leap second as the prior non-leap second
//! if you don't care about sub-second accuracy.
//! You should use the proper formatting to get the raw leap second.
//!
//! All methods accepting fractional seconds will accept such values.
//!
//! ~~~~
//! use chrono::{NaiveDate, NaiveTime, UTC, TimeZone};
//!
//! let t = NaiveTime::from_hms_milli(8, 59, 59, 1_000);
//!
//! let dt1 = NaiveDate::from_ymd(2015, 7, 1).and_hms_micro(8, 59, 59, 1_000_000);
//!
//! let dt2 = UTC.ymd(2015, 6, 30).and_hms_nano(23, 59, 59, 1_000_000_000);
//! # let _ = (t, dt1, dt2);
//! ~~~~
//!
//! Note that the leap second can happen anytime given an appropriate time zone;
//! 2015-07-01 01:23:60 would be a proper leap second if UTC+01:24 had existed.
//! Practically speaking, though, 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.
//!
//! ## Date And Time Arithmetics
//!
//! As a concrete example, let's assume that `03:00:60` and `04:00:60` are leap seconds.
//! (In reality, of course, leap seconds are separated by at least 6 months.)
//!
//! `Time + Duration`:
//!
//! - `03:00:00 + 1s = 03:00:01`.
//! - `03:00:59 + 60s = 03:02:00`.
//! - `03:00:59 + 1s = 03:01:00`.
//! - `03:00:60 + 1s = 03:01:00`.
//! Note that the sum is identical to the previous.
//! - `03:00:60 + 60s = 03:01:59`.
//! - `03:00:60 + 61s = 03:02:00`.
//! - `03:00:60.1 + 0.8s = 03:00:60.9`.
//!
//! `Time - Duration`:
//!
//! - `03:00:00 - 1s = 02:59:59`.
//! - `03:01:00 - 1s = 03:00:59`.
//! - `03:01:00 - 60s = 03:00:00`.
//! - `03:00:60 - 60s = 03:00:00`.
//! Note that the result is identical to the previous.
//! - `03:00:60.7 - 0.4s = 03:00:60.3`.
//! - `03:00:60.7 - 0.9s = 03:00:59.8`.
//!
//! `Time - Time`:
//!
//! - `04:00:00 - 03:00:00 = 3600s`.
//! - `03:01:00 - 03:00:00 = 60s`.
//! - `03:00:60 - 03:00:00 = 60s`.
//! Note that the difference is identical to the previous.
//! - `03:00:60.6 - 03:00:59.4 = 1.2s`.
//! - `03:01:00 - 03:00:59.8 = 0.2s`.
//! - `03:01:00 - 03:00:60.5 = 0.5s`.
//! Note that the difference is larger than the previous,
//! even though the leap second clearly follows the previous whole second.
//! - `04:00:60.9 - 03:00:60.1 =
//! (04:00:60.9 - 04:00:00) + (04:00:00 - 03:01:00) + (03:01:00 - 03:00:60.1) =
//! 60.9s + 3540s + 0.9s = 3601.8s`.
//!
//! In general,
//!
//! - `Time + Duration` unconditionally equals to `Duration + Time`.
//!
//! - `Time - Duration` unconditionally equals to `Time + (-Duration)`.
//!
//! - `Time1 - Time2` unconditionally equals to `-(Time2 - Time1)`.
//!
//! - Associativity does not generally hold, because
//! `(Time + Duration1) - Duration2` no longer equals to `Time + (Duration1 - Duration2)`
//! for two positive durations.
//!
//! - As a special case, `(Time + Duration) - Duration` also does not equal to `Time`.
//!
//! - If you can assume that all durations have the same sign, however,
//! then the associativity holds:
//! `(Time + Duration1) + Duration2` equals to `Time + (Duration1 + Duration2)`
//! for two positive durations.
//!
//! ## Reading And Writing Leap Seconds
//!
//! The "typical" leap seconds on the minute boundary are
//! correctly handled both in the formatting and parsing.
//! The leap second in the human-readable representation
//! will be represented as the second part being 60, as required by ISO 8601.
//!
//! There are hypothetical leap seconds not on the minute boundary
//! nevertheless supported by Chrono.
//! They are allowed for the sake of completeness and consistency;
//! there were several "exotic" time zone offsets with fractional minutes prior to UTC after all.
//! For such cases the human-readable representation is ambiguous
//! and would be read back to the next non-leap second.
//!
//! Since Chrono alone cannot determine any existence of leap seconds,
//! **there is absolutely no guarantee that the leap second read has actually happened**.
use std::{str, fmt, hash}; use std::{str, fmt, hash};
use std::ops::{Add, Sub}; use std::ops::{Add, Sub};
@ -700,19 +797,6 @@ impl hash::Hash for NaiveTime {
/// except when the `NaiveTime` itself represents a leap second /// except when the `NaiveTime` itself represents a leap second
/// in which case the assumption becomes that **there is exactly a single leap second ever**. /// in which case the assumption becomes that **there is exactly a single leap second ever**.
/// ///
/// Therefore, assuming that `03:00:60` is a leap second:
///
/// - `03:00:00 + 1s = 03:00:01`.
/// - `03:00:59 + 1s = 03:01:00`.
/// - `03:00:59 + 60s = 03:02:00`.
/// - `03:00:60 + 1s = 03:01:00`.
/// Note that the sum is identical to the previous; the associativity would no longer hold.
/// - `03:00:60 + 60s = 03:01:59`.
/// - `03:00:60 + 61s = 03:02:00`.
/// - `03:00:60.1 + 0.8s = 03:00:60.9`.
///
/// It can be thought that the clock *forgets* a leap second once it ticked any direction.
///
/// # Example /// # Example
/// ///
/// ~~~~ /// ~~~~
@ -828,23 +912,6 @@ impl Add<Duration> for NaiveTime {
/// in which case the assumption becomes that /// in which case the assumption becomes that
/// **there are exactly one (or two) leap second(s) ever**. /// **there are exactly one (or two) leap second(s) ever**.
/// ///
/// Therefore, assuming that `03:00:60` and `04:00:60` are leap seconds:
///
/// - `04:00:00 - 03:00:00 = 3600s`.
/// - `03:01:00 - 03:00:00 = 60s`.
/// - `03:00:60 - 03:00:00 = 60s`.
/// Note that the difference is identical to the previous.
/// - `03:00:60.6 - 03:00:59.4 = 1.2s`.
/// - `03:01:00 - 03:00:59.8 = 0.2s`.
/// - `03:01:00 - 03:00:60.5 = 0.5s`.
/// Note that the difference is larger than the previous,
/// even though the leap second clearly follows the previous whole second.
/// - `04:00:60.9 - 03:00:60.1 =
/// (04:00:60.9 - 04:00:00) + (04:00:00 - 03:01:00) + (03:01:00 - 03:00:60.1) =
/// 60.9s + 3540s + 0.9s = 3601.8s`.
///
/// Note that `a - b` and `-(b - a)` are still same even under this principle.
///
/// # Example /// # Example
/// ///
/// ~~~~ /// ~~~~
@ -914,16 +981,6 @@ impl Sub<NaiveTime> for NaiveTime {
/// except when the `NaiveTime` itself represents a leap second /// except when the `NaiveTime` itself represents a leap second
/// in which case the assumption becomes that **there is exactly a single leap second ever**. /// in which case the assumption becomes that **there is exactly a single leap second ever**.
/// ///
/// Therefore, assuming that `03:00:60` is a leap second:
///
/// - `03:00:00 - 1s = 02:59:59`.
/// - `03:01:00 - 1s = 03:00:59`.
/// - `03:01:00 - 60s = 03:00:00`.
/// - `03:00:60 - 60s = 03:00:00`.
/// Note that the result is identical to the previous; the associativity would no longer hold.
/// - `03:00:60.7 - 0.4s = 03:00:60.3`.
/// - `03:00:60.7 - 0.9s = 03:00:59.8`.
///
/// # Example /// # Example
/// ///
/// ~~~~ /// ~~~~