Move implementation of from_timestamp* to DateTime

This commit is contained in:
Paul Dicker 2024-02-28 21:59:59 +01:00 committed by Paul Dicker
parent 0c23fd4df5
commit 27a1ee4cdc
2 changed files with 26 additions and 34 deletions

View File

@ -201,7 +201,6 @@ impl<Tz: TimeZone> DateTime<Tz> {
#[inline] #[inline]
#[must_use] #[must_use]
pub const fn timestamp(&self) -> i64 { pub const fn timestamp(&self) -> i64 {
const UNIX_EPOCH_DAY: i64 = 719_163;
let gregorian_day = self.datetime.date().num_days_from_ce() as i64; let gregorian_day = self.datetime.date().num_days_from_ce() as i64;
let seconds_from_midnight = self.datetime.time().num_seconds_from_midnight() as i64; let seconds_from_midnight = self.datetime.time().num_seconds_from_midnight() as i64;
(gregorian_day - UNIX_EPOCH_DAY) * 86_400 + seconds_from_midnight (gregorian_day - UNIX_EPOCH_DAY) * 86_400 + seconds_from_midnight
@ -692,7 +691,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
} }
impl DateTime<Utc> { impl DateTime<Utc> {
/// Makes a new [`DateTime<Utc>`] from the number of non-leap seconds /// Makes a new `DateTime<Utc>` from the number of non-leap seconds
/// since January 1, 1970 0:00:00 UTC (aka "UNIX timestamp") /// since January 1, 1970 0:00:00 UTC (aka "UNIX timestamp")
/// and the number of nanoseconds since the last whole non-leap second. /// and the number of nanoseconds since the last whole non-leap second.
/// ///
@ -714,10 +713,9 @@ impl DateTime<Utc> {
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use chrono::{DateTime, Utc}; /// use chrono::DateTime;
/// ///
/// let dt: DateTime<Utc> = /// let dt = DateTime::from_timestamp(1431648000, 0).expect("invalid timestamp");
/// DateTime::<Utc>::from_timestamp(1431648000, 0).expect("invalid timestamp");
/// ///
/// assert_eq!(dt.to_string(), "2015-05-15 00:00:00 UTC"); /// assert_eq!(dt.to_string(), "2015-05-15 00:00:00 UTC");
/// assert_eq!(DateTime::from_timestamp(dt.timestamp(), dt.timestamp_subsec_nanos()).unwrap(), dt); /// assert_eq!(DateTime::from_timestamp(dt.timestamp(), dt.timestamp_subsec_nanos()).unwrap(), dt);
@ -725,16 +723,20 @@ impl DateTime<Utc> {
#[inline] #[inline]
#[must_use] #[must_use]
pub const fn from_timestamp(secs: i64, nsecs: u32) -> Option<Self> { pub const fn from_timestamp(secs: i64, nsecs: u32) -> Option<Self> {
Some(DateTime { let days = secs.div_euclid(86_400) + UNIX_EPOCH_DAY;
datetime: try_opt!(NaiveDateTime::from_timestamp_opt(secs, nsecs)), let secs = secs.rem_euclid(86_400);
offset: Utc, if days < i32::MIN as i64 || days > i32::MAX as i64 {
}) return None;
}
let date = try_opt!(NaiveDate::from_num_days_from_ce_opt(days as i32));
let time = try_opt!(NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs));
Some(date.and_time(time).and_utc())
} }
/// Makes a new [`DateTime<Utc>`] from the number of non-leap milliseconds /// Makes a new `DateTime<Utc>` from the number of non-leap milliseconds
/// since January 1, 1970 0:00:00.000 UTC (aka "UNIX timestamp"). /// since January 1, 1970 0:00:00.000 UTC (aka "UNIX timestamp").
/// ///
/// This is guaranteed to round-trip with regard to [`timestamp_millis`](DateTime::timestamp_millis). /// This is guaranteed to round-trip with [`timestamp_millis`](DateTime::timestamp_millis).
/// ///
/// If you need to create a `DateTime` with a [`TimeZone`] different from [`Utc`], use /// If you need to create a `DateTime` with a [`TimeZone`] different from [`Utc`], use
/// [`TimeZone::timestamp_millis_opt`] or [`DateTime::with_timezone`]. /// [`TimeZone::timestamp_millis_opt`] or [`DateTime::with_timezone`].
@ -746,10 +748,9 @@ impl DateTime<Utc> {
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use chrono::{DateTime, Utc}; /// use chrono::DateTime;
/// ///
/// let dt: DateTime<Utc> = /// let dt = DateTime::from_timestamp_millis(947638923004).expect("invalid timestamp");
/// DateTime::<Utc>::from_timestamp_millis(947638923004).expect("invalid timestamp");
/// ///
/// assert_eq!(dt.to_string(), "2000-01-12 01:02:03.004 UTC"); /// assert_eq!(dt.to_string(), "2000-01-12 01:02:03.004 UTC");
/// assert_eq!(DateTime::from_timestamp_millis(dt.timestamp_millis()).unwrap(), dt); /// assert_eq!(DateTime::from_timestamp_millis(dt.timestamp_millis()).unwrap(), dt);
@ -757,7 +758,9 @@ impl DateTime<Utc> {
#[inline] #[inline]
#[must_use] #[must_use]
pub const fn from_timestamp_millis(millis: i64) -> Option<Self> { pub const fn from_timestamp_millis(millis: i64) -> Option<Self> {
Some(try_opt!(NaiveDateTime::from_timestamp_millis(millis)).and_utc()) let secs = millis.div_euclid(1000);
let nsecs = millis.rem_euclid(1000) as u32 * 1_000_000;
Self::from_timestamp(secs, nsecs)
} }
/// Creates a new `DateTime<Utc>` from the number of non-leap microseconds /// Creates a new `DateTime<Utc>` from the number of non-leap microseconds
@ -1900,6 +1903,8 @@ where
} }
} }
const UNIX_EPOCH_DAY: i64 = 719_163;
#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))] #[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
fn test_encodable_json<FUtc, FFixed, E>(to_string_utc: FUtc, to_string_fixed: FFixed) fn test_encodable_json<FUtc, FFixed, E>(to_string_utc: FUtc, to_string_fixed: FFixed)
where where

View File

@ -130,8 +130,9 @@ impl NaiveDateTime {
#[inline] #[inline]
#[must_use] #[must_use]
pub const fn from_timestamp(secs: i64, nsecs: u32) -> NaiveDateTime { pub const fn from_timestamp(secs: i64, nsecs: u32) -> NaiveDateTime {
let datetime = NaiveDateTime::from_timestamp_opt(secs, nsecs); let datetime =
expect!(datetime, "invalid or out-of-range datetime") expect!(DateTime::from_timestamp(secs, nsecs), "invalid or out-of-range datetime");
datetime.naive_utc()
} }
/// Creates a new [NaiveDateTime] from milliseconds since the UNIX epoch. /// Creates a new [NaiveDateTime] from milliseconds since the UNIX epoch.
@ -161,9 +162,7 @@ impl NaiveDateTime {
#[inline] #[inline]
#[must_use] #[must_use]
pub const fn from_timestamp_millis(millis: i64) -> Option<NaiveDateTime> { pub const fn from_timestamp_millis(millis: i64) -> Option<NaiveDateTime> {
let secs = millis.div_euclid(1000); Some(try_opt!(DateTime::from_timestamp_millis(millis)).naive_utc())
let nsecs = millis.rem_euclid(1000) as u32 * 1_000_000;
NaiveDateTime::from_timestamp_opt(secs, nsecs)
} }
/// Creates a new [NaiveDateTime] from microseconds since the UNIX epoch. /// Creates a new [NaiveDateTime] from microseconds since the UNIX epoch.
@ -227,8 +226,7 @@ impl NaiveDateTime {
pub const fn from_timestamp_nanos(nanos: i64) -> Option<NaiveDateTime> { pub const fn from_timestamp_nanos(nanos: i64) -> Option<NaiveDateTime> {
let secs = nanos.div_euclid(NANOS_PER_SEC as i64); let secs = nanos.div_euclid(NANOS_PER_SEC as i64);
let nsecs = nanos.rem_euclid(NANOS_PER_SEC as i64) as u32; let nsecs = nanos.rem_euclid(NANOS_PER_SEC as i64) as u32;
Some(try_opt!(DateTime::from_timestamp(secs, nsecs)).naive_utc())
NaiveDateTime::from_timestamp_opt(secs, nsecs)
} }
/// Makes a new `NaiveDateTime` corresponding to a UTC date and time, /// Makes a new `NaiveDateTime` corresponding to a UTC date and time,
@ -264,18 +262,7 @@ impl NaiveDateTime {
#[inline] #[inline]
#[must_use] #[must_use]
pub const fn from_timestamp_opt(secs: i64, nsecs: u32) -> Option<NaiveDateTime> { pub const fn from_timestamp_opt(secs: i64, nsecs: u32) -> Option<NaiveDateTime> {
let days = secs.div_euclid(86_400); Some(try_opt!(DateTime::from_timestamp(secs, nsecs)).naive_utc())
let secs = secs.rem_euclid(86_400);
if days < i32::MIN as i64 || days > i32::MAX as i64 {
return None;
}
let date =
NaiveDate::from_num_days_from_ce_opt(try_opt!((days as i32).checked_add(719_163)));
let time = NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs);
match (date, time) {
(Some(date), Some(time)) => Some(NaiveDateTime { date, time }),
(_, _) => None,
}
} }
/// Parses a string with the specified format string and returns a new `NaiveDateTime`. /// Parses a string with the specified format string and returns a new `NaiveDateTime`.