Skip to content

Commit

Permalink
Make methods on NaiveDateTime const where possible
Browse files Browse the repository at this point in the history
  • Loading branch information
pitdicker committed Sep 12, 2023
1 parent e3321d1 commit 9043fa4
Showing 1 changed file with 34 additions and 31 deletions.
65 changes: 34 additions & 31 deletions src/naive/datetime/mod.rs
Expand Up @@ -20,7 +20,9 @@ use crate::format::{parse, parse_and_remainder, ParseError, ParseResult, Parsed,
use crate::format::{Fixed, Item, Numeric, Pad};
use crate::naive::{Days, IsoWeek, NaiveDate, NaiveTime};
use crate::offset::Utc;
use crate::{DateTime, Datelike, LocalResult, Months, TimeZone, Timelike, Weekday};
use crate::{
expect, try_opt, DateTime, Datelike, LocalResult, Months, TimeZone, Timelike, Weekday,
};

#[cfg(feature = "rustc-serialize")]
pub(super) mod rustc_serialize;
Expand Down Expand Up @@ -122,9 +124,9 @@ impl NaiveDateTime {
#[deprecated(since = "0.4.23", note = "use `from_timestamp_opt()` instead")]
#[inline]
#[must_use]
pub fn from_timestamp(secs: i64, nsecs: u32) -> NaiveDateTime {
pub const fn from_timestamp(secs: i64, nsecs: u32) -> NaiveDateTime {

Check warning on line 127 in src/naive/datetime/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/naive/datetime/mod.rs#L127

Added line #L127 was not covered by tests
let datetime = NaiveDateTime::from_timestamp_opt(secs, nsecs);
datetime.expect("invalid or out-of-range datetime")
expect!(datetime, "invalid or out-of-range datetime")

Check warning on line 129 in src/naive/datetime/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/naive/datetime/mod.rs#L129

Added line #L129 was not covered by tests
}

/// Creates a new [NaiveDateTime] from milliseconds since the UNIX epoch.
Expand Down Expand Up @@ -153,7 +155,7 @@ impl NaiveDateTime {
/// ```
#[inline]
#[must_use]
pub fn from_timestamp_millis(millis: i64) -> Option<NaiveDateTime> {
pub const fn from_timestamp_millis(millis: i64) -> Option<NaiveDateTime> {
let secs = millis.div_euclid(1000);
let nsecs = millis.rem_euclid(1000) as u32 * 1_000_000;
NaiveDateTime::from_timestamp_opt(secs, nsecs)
Expand Down Expand Up @@ -185,7 +187,7 @@ impl NaiveDateTime {
/// ```
#[inline]
#[must_use]
pub fn from_timestamp_micros(micros: i64) -> Option<NaiveDateTime> {
pub const fn from_timestamp_micros(micros: i64) -> Option<NaiveDateTime> {
let secs = micros.div_euclid(1_000_000);
let nsecs = micros.rem_euclid(1_000_000) as u32 * 1000;
NaiveDateTime::from_timestamp_opt(secs, nsecs)
Expand Down Expand Up @@ -222,13 +224,14 @@ impl NaiveDateTime {
/// ```
#[inline]
#[must_use]
pub 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);
let secs = secs.rem_euclid(86_400);
let date = i32::try_from(days)
.ok()
.and_then(|days| days.checked_add(719_163))
.and_then(NaiveDate::from_num_days_from_ce_opt);
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 }),
Expand Down Expand Up @@ -392,10 +395,10 @@ impl NaiveDateTime {
/// ```
#[inline]
#[must_use]
pub fn timestamp(&self) -> i64 {
pub const fn timestamp(&self) -> i64 {
const UNIX_EPOCH_DAY: i64 = 719_163;
let gregorian_day = i64::from(self.date.num_days_from_ce());
let seconds_from_midnight = i64::from(self.time.num_seconds_from_midnight());
let gregorian_day = self.date.num_days_from_ce() as i64;
let seconds_from_midnight = self.time.num_seconds_from_midnight() as i64;
(gregorian_day - UNIX_EPOCH_DAY) * 86_400 + seconds_from_midnight
}

Expand All @@ -420,9 +423,9 @@ impl NaiveDateTime {
/// ```
#[inline]
#[must_use]
pub fn timestamp_millis(&self) -> i64 {
pub const fn timestamp_millis(&self) -> i64 {
let as_ms = self.timestamp() * 1000;
as_ms + i64::from(self.timestamp_subsec_millis())
as_ms + self.timestamp_subsec_millis() as i64
}

/// Returns the number of non-leap *microseconds* since midnight on January 1, 1970.
Expand All @@ -443,9 +446,9 @@ impl NaiveDateTime {
/// ```
#[inline]
#[must_use]
pub fn timestamp_micros(&self) -> i64 {
pub const fn timestamp_micros(&self) -> i64 {
let as_us = self.timestamp() * 1_000_000;
as_us + i64::from(self.timestamp_subsec_micros())
as_us + self.timestamp_subsec_micros() as i64
}

/// Returns the number of non-leap *nanoseconds* since midnight on January 1, 1970.
Expand Down Expand Up @@ -523,7 +526,7 @@ impl NaiveDateTime {
/// ```
#[inline]
#[must_use]
pub fn timestamp_subsec_millis(&self) -> u32 {
pub const fn timestamp_subsec_millis(&self) -> u32 {
self.timestamp_subsec_nanos() / 1_000_000
}

Expand All @@ -545,7 +548,7 @@ impl NaiveDateTime {
/// ```
#[inline]
#[must_use]
pub fn timestamp_subsec_micros(&self) -> u32 {
pub const fn timestamp_subsec_micros(&self) -> u32 {
self.timestamp_subsec_nanos() / 1_000
}

Expand All @@ -567,7 +570,7 @@ impl NaiveDateTime {
/// ```
#[inline]
#[must_use]
pub fn timestamp_subsec_nanos(&self) -> u32 {
pub const fn timestamp_subsec_nanos(&self) -> u32 {
self.time.nanosecond()
}

Expand Down Expand Up @@ -647,7 +650,7 @@ impl NaiveDateTime {
return None;
}

let date = self.date.checked_add_signed(OldDuration::seconds(rhs))?;
let date = try_opt!(self.date.checked_add_signed(OldDuration::seconds(rhs)));
Some(NaiveDateTime { date, time })
}

Expand Down Expand Up @@ -677,8 +680,8 @@ impl NaiveDateTime {
/// );
/// ```
#[must_use]
pub fn checked_add_months(self, rhs: Months) -> Option<NaiveDateTime> {
Some(Self { date: self.date.checked_add_months(rhs)?, time: self.time })
pub const fn checked_add_months(self, rhs: Months) -> Option<NaiveDateTime> {
Some(Self { date: try_opt!(self.date.checked_add_months(rhs)), time: self.time })
}

/// Subtracts given `Duration` from the current date and time.
Expand Down Expand Up @@ -783,24 +786,24 @@ impl NaiveDateTime {
/// );
/// ```
#[must_use]
pub fn checked_sub_months(self, rhs: Months) -> Option<NaiveDateTime> {
Some(Self { date: self.date.checked_sub_months(rhs)?, time: self.time })
pub const fn checked_sub_months(self, rhs: Months) -> Option<NaiveDateTime> {
Some(Self { date: try_opt!(self.date.checked_sub_months(rhs)), time: self.time })
}

/// Add a duration in [`Days`] to the date part of the `NaiveDateTime`
///
/// Returns `None` if the resulting date would be out of range.
#[must_use]
pub fn checked_add_days(self, days: Days) -> Option<Self> {
Some(Self { date: self.date.checked_add_days(days)?, ..self })
pub const fn checked_add_days(self, days: Days) -> Option<Self> {
Some(Self { date: try_opt!(self.date.checked_add_days(days)), ..self })
}

/// Subtract a duration in [`Days`] from the date part of the `NaiveDateTime`
///
/// Returns `None` if the resulting date would be out of range.
#[must_use]
pub fn checked_sub_days(self, days: Days) -> Option<Self> {
Some(Self { date: self.date.checked_sub_days(days)?, ..self })
pub const fn checked_sub_days(self, days: Days) -> Option<Self> {
Some(Self { date: try_opt!(self.date.checked_sub_days(days)), ..self })
}

/// Subtracts another `NaiveDateTime` from the current date and time.
Expand Down Expand Up @@ -960,8 +963,8 @@ impl NaiveDateTime {
/// assert_eq!(dt.timezone(), Utc);
/// ```
#[must_use]
pub fn and_utc(&self) -> DateTime<Utc> {
Utc.from_utc_datetime(self)
pub const fn and_utc(&self) -> DateTime<Utc> {
DateTime::from_naive_utc_and_offset(*self, Utc)
}

/// The minimum possible `NaiveDateTime`.
Expand Down

0 comments on commit 9043fa4

Please sign in to comment.