Merge remote-tracking branch 'origin/master' into feature/option

This commit is contained in:
Brandon W Maister 2019-04-07 17:54:08 -04:00
commit 97cc89e1fa
5 changed files with 85 additions and 5 deletions

View File

@ -28,6 +28,7 @@ default = ["clock"]
clock = ["time"] clock = ["time"]
[dependencies] [dependencies]
libc = { version = "0.2", default-features = false }
time = { version = "0.1.39", optional = true } time = { version = "0.1.39", optional = true }
num-integer = { version = "0.1.36", default-features = false } num-integer = { version = "0.1.36", default-features = false }
num-traits = { version = "0.2", default-features = false } num-traits = { version = "0.2", default-features = false }

View File

@ -4,6 +4,8 @@
//! Date and time parsing routines. //! Date and time parsing routines.
#![allow(deprecated)]
use std::usize; use std::usize;
use Weekday; use Weekday;

View File

@ -5,6 +5,8 @@
* Various scanning routines for the parser. * Various scanning routines for the parser.
*/ */
#![allow(deprecated)]
use Weekday; use Weekday;
use super::{ParseResult, TOO_SHORT, INVALID, OUT_OF_RANGE}; use super::{ParseResult, TOO_SHORT, INVALID, OUT_OF_RANGE};

View File

@ -305,21 +305,33 @@ 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.
/// ///
/// # Panics
///
/// Note also that this does reduce the number of years that can be /// Note also that this does reduce the number of years that can be
/// represented from ~584 Billion to ~584. (If this is a problem, /// represented from ~584 Billion to ~584 years. The dates that can be
/// please file an issue to let me know what domain needs nanosecond /// represented as nanoseconds are between 1677-09-21T00:12:44.0 and
/// precision over millenia, I'm curious.) /// 2262-04-11T23:47:16.854775804.
///
/// (If this is a problem, please file an issue to let me know what domain
/// needs nanosecond precision over millenia, I'm curious.)
/// ///
/// # Example /// # Example
/// ///
/// ~~~~ /// ~~~~
/// use chrono::NaiveDate; /// use chrono::{NaiveDate, NaiveDateTime};
/// ///
/// let dt = NaiveDate::from_ymd(1970, 1, 1).and_hms_nano(0, 0, 1, 444); /// let dt = NaiveDate::from_ymd(1970, 1, 1).and_hms_nano(0, 0, 1, 444);
/// assert_eq!(dt.timestamp_nanos(), 1_000_000_444); /// assert_eq!(dt.timestamp_nanos(), 1_000_000_444);
/// ///
/// let dt = NaiveDate::from_ymd(2001, 9, 9).and_hms_nano(1, 46, 40, 555); /// let dt = NaiveDate::from_ymd(2001, 9, 9).and_hms_nano(1, 46, 40, 555);
/// assert_eq!(dt.timestamp_nanos(), 1_000_000_000_000_000_555); ///
/// const A_BILLION: i64 = 1_000_000_000;
/// let nanos = dt.timestamp_nanos();
/// assert_eq!(nanos, 1_000_000_000_000_000_555);
/// assert_eq!(
/// dt,
/// NaiveDateTime::from_timestamp(nanos / A_BILLION, (nanos % A_BILLION) as u32)
/// );
/// ~~~~ /// ~~~~
#[inline] #[inline]
pub fn timestamp_nanos(&self) -> i64 { pub fn timestamp_nanos(&self) -> i64 {
@ -2348,4 +2360,24 @@ mod tests {
let time = base + Duration::microseconds(t); let time = base + Duration::microseconds(t);
assert_eq!(t, time.signed_duration_since(base).num_microseconds().unwrap()); assert_eq!(t, time.signed_duration_since(base).num_microseconds().unwrap());
} }
#[test]
fn test_nanosecond_range() {
const A_BILLION: i64 = 1_000_000_000;
let maximum = "2262-04-11T23:47:16.854775804";
let parsed: NaiveDateTime = maximum.parse().unwrap();
let nanos = parsed.timestamp_nanos();
assert_eq!(
parsed,
NaiveDateTime::from_timestamp(nanos / A_BILLION, (nanos % A_BILLION) as u32)
);
let minimum = "1677-09-21T00:12:44.000000000";
let parsed: NaiveDateTime = minimum.parse().unwrap();
let nanos = parsed.timestamp_nanos();
assert_eq!(
parsed,
NaiveDateTime::from_timestamp(nanos / A_BILLION, (nanos % A_BILLION) as u32)
);
}
} }

View File

@ -381,6 +381,28 @@ pub trait TimeZone: Sized + Clone {
self.timestamp_opt(secs, millis as u32 * 1_000_000) self.timestamp_opt(secs, millis as u32 * 1_000_000)
} }
/// Makes a new `DateTime` from the number of non-leap nanoseconds
/// since January 1, 1970 0:00:00 UTC (aka "UNIX timestamp").
///
/// Unlike [`timestamp_millis`](#method.timestamp_millis), this never
/// panics.
///
/// # Example
///
/// ~~~~
/// use chrono::{Utc, TimeZone};
///
/// assert_eq!(Utc.timestamp_nanos(1431648000000000).timestamp(), 1431648);
/// ~~~~
fn timestamp_nanos(&self, nanos: i64) -> DateTime<Self> {
let (mut secs, mut nanos) = (nanos / 1_000_000_000, nanos % 1_000_000_000);
if nanos < 0 {
secs -= 1;
nanos += 1_000_000_000;
}
self.timestamp_opt(secs, nanos as u32).unwrap()
}
/// Parses a string with the specified format string and /// Parses a string with the specified format string and
/// returns a `DateTime` with the current offset. /// returns a `DateTime` with the current offset.
/// See the [`format::strftime` module](../format/strftime/index.html) /// See the [`format::strftime` module](../format/strftime/index.html)
@ -466,4 +488,25 @@ mod tests {
let dt = Utc.timestamp_millis(-3600000); let dt = Utc.timestamp_millis(-3600000);
assert_eq!(dt.to_string(), "1969-12-31 23:00:00 UTC"); assert_eq!(dt.to_string(), "1969-12-31 23:00:00 UTC");
} }
#[test]
fn test_negative_nanos() {
let dt = Utc.timestamp_nanos(-1_000_000_000);
assert_eq!(dt.to_string(), "1969-12-31 23:59:59 UTC");
let dt = Utc.timestamp_nanos(-999_999_999);
assert_eq!(dt.to_string(), "1969-12-31 23:59:59.000000001 UTC");
let dt = Utc.timestamp_nanos(-1);
assert_eq!(dt.to_string(), "1969-12-31 23:59:59.999999999 UTC");
let dt = Utc.timestamp_nanos(-60_000_000_000);
assert_eq!(dt.to_string(), "1969-12-31 23:59:00 UTC");
let dt = Utc.timestamp_nanos(-3_600_000_000_000);
assert_eq!(dt.to_string(), "1969-12-31 23:00:00 UTC");
}
#[test]
fn test_nanos_never_panics() {
Utc.timestamp_nanos(i64::max_value());
Utc.timestamp_nanos(i64::default());
Utc.timestamp_nanos(i64::min_value());
}
} }