diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4c1d62bab7..55e6c6ce7f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,9 +2,8 @@ name: lint on: push: - branches: [main, master] + branches: [main, master, 0.4.x] pull_request: - branches: [main, master] jobs: lint: diff --git a/.github/workflows/test-release.yml b/.github/workflows/test-release.yml index 67de1c1a18..f10b3ee5e4 100644 --- a/.github/workflows/test-release.yml +++ b/.github/workflows/test-release.yml @@ -2,9 +2,7 @@ name: Release Test on: push: - branches: ["rel*"] - pull_request: - branches: ["rel*"] + branches: ["rel*", "0.4.x"] # From here down this should be exactly the same as test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c9f39f947d..dfb40f0c08 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,7 +2,7 @@ name: All Tests and Builds on: push: - branches: [main] + branches: [main, 0.4.x] pull_request: paths: - "**.rs" diff --git a/src/naive/datetime/mod.rs b/src/naive/datetime/mod.rs index c0e851e4e3..3e92895a45 100644 --- a/src/naive/datetime/mod.rs +++ b/src/naive/datetime/mod.rs @@ -5,6 +5,7 @@ #[cfg(any(feature = "alloc", feature = "std", test))] use core::borrow::Borrow; +use core::convert::TryFrom; use core::ops::{Add, AddAssign, Sub, SubAssign}; use core::{fmt, str}; @@ -39,6 +40,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; @@ -131,6 +137,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 { + let mut secs = millis / 1000; + if millis < 0 { + secs = secs.checked_sub(1)?; + } + + let nsecs = (millis % 1000).abs(); + let mut nsecs = u32::try_from(nsecs).ok()? * NANOS_IN_MILLISECOND; + if secs < 0 { + nsecs = NANOS_IN_SECOND.checked_sub(nsecs)?; + } + + 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")