mirror of
https://github.com/chronotope/chrono.git
synced 2025-09-28 05:21:39 +00:00
Add from_timestamp_nanos (#1357)
* Add from_timestamp_nanos Add and implement from_timestamp_nanos and add unit test for it * Fix lint check error * Add pub(crate) for NANOS_PER_SEC * Replace number with constant variable
This commit is contained in:
parent
6f3ab9dd5a
commit
e1a9494e24
@ -24,7 +24,7 @@ const NANOS_PER_MICRO: i32 = 1000;
|
||||
/// The number of nanoseconds in a millisecond.
|
||||
const NANOS_PER_MILLI: i32 = 1_000_000;
|
||||
/// The number of nanoseconds in seconds.
|
||||
const NANOS_PER_SEC: i32 = 1_000_000_000;
|
||||
pub(crate) const NANOS_PER_SEC: i32 = 1_000_000_000;
|
||||
/// The number of microseconds per second.
|
||||
const MICROS_PER_SEC: i64 = 1_000_000;
|
||||
/// The number of milliseconds per second.
|
||||
|
@ -13,7 +13,7 @@ use core::{fmt, str};
|
||||
#[cfg(feature = "rkyv")]
|
||||
use rkyv::{Archive, Deserialize, Serialize};
|
||||
|
||||
use crate::duration::Duration as OldDuration;
|
||||
use crate::duration::{Duration as OldDuration, NANOS_PER_SEC};
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::format::DelayedFormat;
|
||||
use crate::format::{parse, parse_and_remainder, ParseError, ParseResult, Parsed, StrftimeItems};
|
||||
@ -197,6 +197,39 @@ impl NaiveDateTime {
|
||||
NaiveDateTime::from_timestamp_opt(secs, nsecs)
|
||||
}
|
||||
|
||||
/// Creates a new [NaiveDateTime] from nanoseconds since the UNIX epoch.
|
||||
///
|
||||
/// The UNIX epoch starts on midnight, January 1, 1970, UTC.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `None` if the number of nanoseconds would be out of range for a `NaiveDateTime`
|
||||
/// (more than ca. 262,000 years away from common era)
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use chrono::NaiveDateTime;
|
||||
/// let timestamp_nanos: i64 = 1662921288_000_000_000; //Sunday, September 11, 2022 6:34:48 PM
|
||||
/// let naive_datetime = NaiveDateTime::from_timestamp_nanos(timestamp_nanos);
|
||||
/// assert!(naive_datetime.is_some());
|
||||
/// assert_eq!(timestamp_nanos, naive_datetime.unwrap().timestamp_nanos_opt().unwrap());
|
||||
///
|
||||
/// // Negative timestamps (before the UNIX epoch) are supported as well.
|
||||
/// let timestamp_nanos: i64 = -2208936075_000_000_000; //Mon Jan 01 1900 14:38:45 GMT+0000
|
||||
/// let naive_datetime = NaiveDateTime::from_timestamp_nanos(timestamp_nanos);
|
||||
/// assert!(naive_datetime.is_some());
|
||||
/// assert_eq!(timestamp_nanos, naive_datetime.unwrap().timestamp_nanos_opt().unwrap());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub const fn from_timestamp_nanos(nanos: i64) -> Option<NaiveDateTime> {
|
||||
let secs = nanos.div_euclid(NANOS_PER_SEC as i64);
|
||||
let nsecs = nanos.rem_euclid(NANOS_PER_SEC as i64) as u32;
|
||||
|
||||
NaiveDateTime::from_timestamp_opt(secs, nsecs)
|
||||
}
|
||||
|
||||
/// 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")
|
||||
|
@ -78,6 +78,57 @@ fn test_datetime_from_timestamp_micros() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_from_timestamp_nanos() {
|
||||
let valid_map = [
|
||||
(1662921288000000000, "2022-09-11 18:34:48.000000000"),
|
||||
(1662921288123456000, "2022-09-11 18:34:48.123456000"),
|
||||
(1662921288123456789, "2022-09-11 18:34:48.123456789"),
|
||||
(1662921287890000000, "2022-09-11 18:34:47.890000000"),
|
||||
(-2208936075000000000, "1900-01-01 14:38:45.000000000"),
|
||||
(-5337182663000000000, "1800-11-15 01:15:37.000000000"),
|
||||
(0, "1970-01-01 00:00:00.000000000"),
|
||||
(119731017000000000, "1973-10-17 18:36:57.000000000"),
|
||||
(1234567890000000000, "2009-02-13 23:31:30.000000000"),
|
||||
(2034061609000000000, "2034-06-16 09:06:49.000000000"),
|
||||
];
|
||||
|
||||
for (timestamp_nanos, _formatted) in valid_map.iter().copied() {
|
||||
let naive_datetime = NaiveDateTime::from_timestamp_nanos(timestamp_nanos).unwrap();
|
||||
assert_eq!(timestamp_nanos, naive_datetime.timestamp_nanos_opt().unwrap());
|
||||
#[cfg(feature = "alloc")]
|
||||
assert_eq!(naive_datetime.format("%F %T%.9f").to_string(), _formatted);
|
||||
}
|
||||
|
||||
const A_BILLION: i64 = 1_000_000_000;
|
||||
// Maximum datetime in nanoseconds
|
||||
let maximum = "2262-04-11T23:47:16.854775804";
|
||||
let parsed: NaiveDateTime = maximum.parse().unwrap();
|
||||
let nanos = parsed.timestamp_nanos_opt().unwrap();
|
||||
assert_eq!(
|
||||
NaiveDateTime::from_timestamp_nanos(nanos).unwrap(),
|
||||
NaiveDateTime::from_timestamp_opt(nanos / A_BILLION, (nanos % A_BILLION) as u32).unwrap()
|
||||
);
|
||||
// Minimum datetime in nanoseconds
|
||||
let minimum = "1677-09-21T00:12:44.000000000";
|
||||
let parsed: NaiveDateTime = minimum.parse().unwrap();
|
||||
let nanos = parsed.timestamp_nanos_opt().unwrap();
|
||||
assert_eq!(
|
||||
NaiveDateTime::from_timestamp_nanos(nanos).unwrap(),
|
||||
NaiveDateTime::from_timestamp_opt(nanos / A_BILLION, (nanos % A_BILLION) as u32).unwrap()
|
||||
);
|
||||
|
||||
// Test that the result of `from_timestamp_nanos` compares equal to
|
||||
// that of `from_timestamp_opt`.
|
||||
let secs_test = [0, 1, 2, 1000, 1234, 12345678, -1, -2, -1000, -12345678];
|
||||
for secs in secs_test.iter().copied() {
|
||||
assert_eq!(
|
||||
NaiveDateTime::from_timestamp_nanos(secs * 1_000_000_000),
|
||||
NaiveDateTime::from_timestamp_opt(secs, 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_from_timestamp() {
|
||||
let from_timestamp = |secs| NaiveDateTime::from_timestamp_opt(secs, 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user