Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NaiveDateTime::from_timestamp_millis(_opt) #818

Merged
merged 5 commits into from Sep 19, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/naive/datetime/mod.rs
Expand Up @@ -35,6 +35,11 @@ mod tests;
/// touching that call when we are already sure that it WILL overflow...
const MAX_SECS_BITS: usize = 44;

/// Number of nanoseconds in a millisecond
const NANOS_IN_MILLISECOND: u32 = 1_000_000;
/// Number of nanoseconds in a second
const NANOS_IN_SECOND: u32 = 1000 * NANOS_IN_MILLISECOND;

/// The minimum possible `NaiveDateTime`.
#[deprecated(since = "0.4.20", note = "Use NaiveDateTime::MIN instead")]
pub const MIN_DATETIME: NaiveDateTime = NaiveDateTime::MIN;
Expand Down Expand Up @@ -127,6 +132,43 @@ impl NaiveDateTime {
datetime.expect("invalid or out-of-range datetime")
}

/// Creates a new [NaiveDateTime] from milliseconds since the UNIX epoch.
///
/// The UNIX epoch starts on midnight, January 1, 1970, UTC.
///
/// Returns `None` on an out-of-range number of milliseconds.
///
/// # Example
///
/// ```
/// use chrono::NaiveDateTime;
/// let timestamp_millis: i64 = 1662921288; //Sunday, September 11, 2022 6:34:48 PM
/// let naive_datetime = NaiveDateTime::from_timestamp_millis(timestamp_millis);
/// assert!(naive_datetime.is_some());
/// assert_eq!(timestamp_millis, naive_datetime.unwrap().timestamp_millis());
///
/// // Negative timestamps (before the UNIX epoch) are supported as well.
/// let timestamp_millis: i64 = -2208936075; //Mon Jan 01 1900 14:38:45 GMT+0000
/// let naive_datetime = NaiveDateTime::from_timestamp_millis(timestamp_millis);
/// assert!(naive_datetime.is_some());
/// assert_eq!(timestamp_millis, naive_datetime.unwrap().timestamp_millis());
/// ```
#[inline]
pub fn from_timestamp_millis(millis: i64) -> Option<NaiveDateTime> {
let secs = millis / 1000;

if millis < 0 {
let nsecs = u32::try_from((millis % 1000).abs()).ok()? * NANOS_IN_MILLISECOND;
NaiveDateTime::from_timestamp_opt(
secs.checked_sub(1)?,
NANOS_IN_SECOND.checked_sub(nsecs)?,
)
} else {
let nsecs = u32::try_from(millis % 1000).ok()? * NANOS_IN_MILLISECOND;
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")
Expand Down