summaryrefslogtreecommitdiffstats
path: root/vendor/time/src/date_time.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/time/src/date_time.rs')
-rw-r--r--vendor/time/src/date_time.rs123
1 files changed, 77 insertions, 46 deletions
diff --git a/vendor/time/src/date_time.rs b/vendor/time/src/date_time.rs
index 819f6d36b..53cae5eb4 100644
--- a/vendor/time/src/date_time.rs
+++ b/vendor/time/src/date_time.rs
@@ -16,10 +16,16 @@ use std::io;
#[cfg(feature = "std")]
use std::time::SystemTime;
+use deranged::RangedI64;
+
use crate::convert::*;
use crate::date::{MAX_YEAR, MIN_YEAR};
#[cfg(feature = "formatting")]
use crate::formatting::Formattable;
+use crate::internal_macros::{
+ bug, cascade, const_try, const_try_opt, div_floor, ensure_ranged, expect_opt, impl_add_assign,
+ impl_sub_assign,
+};
#[cfg(feature = "parsing")]
use crate::parsing::{Parsable, Parsed};
use crate::{error, util, Date, Duration, Month, Time, UtcOffset, Weekday};
@@ -191,7 +197,10 @@ pub(crate) const fn maybe_offset_from_offset<O: MaybeOffset>(
// endregion const trait methods hacks
/// The Julian day of the Unix epoch.
-const UNIX_EPOCH_JULIAN_DAY: i32 = Date::__from_ordinal_date_unchecked(1970, 1).to_julian_day();
+// Safety: `ordinal` is not zero.
+#[allow(clippy::undocumented_unsafe_blocks)]
+const UNIX_EPOCH_JULIAN_DAY: i32 =
+ unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.to_julian_day();
pub struct DateTime<O: MaybeOffset> {
pub(crate) date: Date,
@@ -226,7 +235,8 @@ impl DateTime<offset_kind::None> {
impl DateTime<offset_kind::Fixed> {
pub const UNIX_EPOCH: Self = Self {
- date: Date::__from_ordinal_date_unchecked(1970, 1),
+ // Safety: `ordinal` is not zero.
+ date: unsafe { Date::__from_ordinal_date_unchecked(1970, 1) },
time: Time::MIDNIGHT,
offset: UtcOffset::UTC,
};
@@ -248,28 +258,27 @@ impl<O: MaybeOffset> DateTime<O> {
where
O: HasLogicalOffset,
{
- #[allow(clippy::missing_docs_in_private_items)]
- const MIN_TIMESTAMP: i64 = Date::MIN.midnight().assume_utc().unix_timestamp();
- #[allow(clippy::missing_docs_in_private_items)]
- const MAX_TIMESTAMP: i64 = Date::MAX
- .with_time(Time::__from_hms_nanos_unchecked(23, 59, 59, 999_999_999))
- .assume_utc()
- .unix_timestamp();
-
- ensure_value_in_range!(timestamp in MIN_TIMESTAMP => MAX_TIMESTAMP);
+ type Timestamp = RangedI64<
+ { Date::MIN.midnight().assume_utc().unix_timestamp() },
+ { Date::MAX.with_time(Time::MAX).assume_utc().unix_timestamp() },
+ >;
+ ensure_ranged!(Timestamp: timestamp);
// Use the unchecked method here, as the input validity has already been verified.
let date = Date::from_julian_day_unchecked(
- UNIX_EPOCH_JULIAN_DAY + div_floor!(timestamp, Second.per(Day) as i64) as i32,
+ UNIX_EPOCH_JULIAN_DAY + div_floor!(timestamp, Second::per(Day) as i64) as i32,
);
- let seconds_within_day = timestamp.rem_euclid(Second.per(Day) as _);
- let time = Time::__from_hms_nanos_unchecked(
- (seconds_within_day / Second.per(Hour) as i64) as _,
- ((seconds_within_day % Second.per(Hour) as i64) / Minute.per(Hour) as i64) as _,
- (seconds_within_day % Second.per(Minute) as i64) as _,
- 0,
- );
+ let seconds_within_day = timestamp.rem_euclid(Second::per(Day) as _);
+ // Safety: All values are in range.
+ let time = unsafe {
+ Time::__from_hms_nanos_unchecked(
+ (seconds_within_day / Second::per(Hour) as i64) as _,
+ ((seconds_within_day % Second::per(Hour) as i64) / Minute::per(Hour) as i64) as _,
+ (seconds_within_day % Second::per(Minute) as i64) as _,
+ 0,
+ )
+ };
Ok(Self {
date,
@@ -284,17 +293,20 @@ impl<O: MaybeOffset> DateTime<O> {
{
let datetime = const_try!(Self::from_unix_timestamp(div_floor!(
timestamp,
- Nanosecond.per(Second) as i128
+ Nanosecond::per(Second) as i128
) as i64));
Ok(Self {
date: datetime.date,
- time: Time::__from_hms_nanos_unchecked(
- datetime.hour(),
- datetime.minute(),
- datetime.second(),
- timestamp.rem_euclid(Nanosecond.per(Second) as _) as u32,
- ),
+ // Safety: `nanosecond` is in range due to `rem_euclid`.
+ time: unsafe {
+ Time::__from_hms_nanos_unchecked(
+ datetime.hour(),
+ datetime.minute(),
+ datetime.second(),
+ timestamp.rem_euclid(Nanosecond::per(Second) as _) as u32,
+ )
+ },
offset: maybe_offset_from_offset::<O>(UtcOffset::UTC),
})
}
@@ -455,9 +467,9 @@ impl<O: MaybeOffset> DateTime<O> {
let offset = maybe_offset_as_offset::<O>(self.offset).whole_seconds() as i64;
let days =
- (self.to_julian_day() as i64 - UNIX_EPOCH_JULIAN_DAY as i64) * Second.per(Day) as i64;
- let hours = self.hour() as i64 * Second.per(Hour) as i64;
- let minutes = self.minute() as i64 * Second.per(Minute) as i64;
+ (self.to_julian_day() as i64 - UNIX_EPOCH_JULIAN_DAY as i64) * Second::per(Day) as i64;
+ let hours = self.hour() as i64 * Second::per(Hour) as i64;
+ let minutes = self.minute() as i64 * Second::per(Minute) as i64;
let seconds = self.second() as i64;
days + hours + minutes + seconds - offset
}
@@ -466,7 +478,7 @@ impl<O: MaybeOffset> DateTime<O> {
where
O: HasLogicalOffset,
{
- self.unix_timestamp() as i128 * Nanosecond.per(Second) as i128 + self.nanosecond() as i128
+ self.unix_timestamp() as i128 * Nanosecond::per(Second) as i128 + self.nanosecond() as i128
}
// endregion unix timestamp getters
// endregion: getters
@@ -526,7 +538,8 @@ impl<O: MaybeOffset> DateTime<O> {
}
Some(DateTime {
- date: Date::__from_ordinal_date_unchecked(year, ordinal),
+ // Safety: `ordinal` is not zero.
+ date: unsafe { Date::__from_ordinal_date_unchecked(year, ordinal) },
time,
offset,
})
@@ -558,12 +571,12 @@ impl<O: MaybeOffset> DateTime<O> {
let mut ordinal = ordinal as i16;
// Cascade the values twice. This is needed because the values are adjusted twice above.
- cascade!(second in 0..Second.per(Minute) as i16 => minute);
- cascade!(second in 0..Second.per(Minute) as i16 => minute);
- cascade!(minute in 0..Minute.per(Hour) as i16 => hour);
- cascade!(minute in 0..Minute.per(Hour) as i16 => hour);
- cascade!(hour in 0..Hour.per(Day) as i8 => ordinal);
- cascade!(hour in 0..Hour.per(Day) as i8 => ordinal);
+ cascade!(second in 0..Second::per(Minute) as i16 => minute);
+ cascade!(second in 0..Second::per(Minute) as i16 => minute);
+ cascade!(minute in 0..Minute::per(Hour) as i16 => hour);
+ cascade!(minute in 0..Minute::per(Hour) as i16 => hour);
+ cascade!(hour in 0..Hour::per(Day) as i8 => ordinal);
+ cascade!(hour in 0..Hour::per(Day) as i8 => ordinal);
cascade!(ordinal => year);
debug_assert!(ordinal > 0);
@@ -572,12 +585,15 @@ impl<O: MaybeOffset> DateTime<O> {
(
year,
ordinal as _,
- Time::__from_hms_nanos_unchecked(
- hour as _,
- minute as _,
- second as _,
- self.nanosecond(),
- ),
+ // Safety: The cascades above ensure the values are in range.
+ unsafe {
+ Time::__from_hms_nanos_unchecked(
+ hour as _,
+ minute as _,
+ second as _,
+ self.nanosecond(),
+ )
+ },
)
}
// endregion to offset
@@ -653,6 +669,7 @@ impl<O: MaybeOffset> DateTime<O> {
// endregion saturating arithmetic
// region: replacement
+ #[must_use = "this does not modify the original value"]
pub const fn replace_time(self, time: Time) -> Self {
Self {
date: self.date,
@@ -661,6 +678,7 @@ impl<O: MaybeOffset> DateTime<O> {
}
}
+ #[must_use = "this does not modify the original value"]
pub const fn replace_date(self, date: Date) -> Self {
Self {
date,
@@ -669,6 +687,7 @@ impl<O: MaybeOffset> DateTime<O> {
}
}
+ #[must_use = "this does not modify the original value"]
pub const fn replace_date_time(self, date_time: DateTime<offset_kind::None>) -> Self
where
O: HasLogicalOffset,
@@ -680,6 +699,7 @@ impl<O: MaybeOffset> DateTime<O> {
}
}
+ #[must_use = "this does not modify the original value"]
pub const fn replace_year(self, year: i32) -> Result<Self, error::ComponentRange> {
Ok(Self {
date: const_try!(self.date.replace_year(year)),
@@ -688,6 +708,7 @@ impl<O: MaybeOffset> DateTime<O> {
})
}
+ #[must_use = "this does not modify the original value"]
pub const fn replace_month(self, month: Month) -> Result<Self, error::ComponentRange> {
Ok(Self {
date: const_try!(self.date.replace_month(month)),
@@ -696,6 +717,7 @@ impl<O: MaybeOffset> DateTime<O> {
})
}
+ #[must_use = "this does not modify the original value"]
pub const fn replace_day(self, day: u8) -> Result<Self, error::ComponentRange> {
Ok(Self {
date: const_try!(self.date.replace_day(day)),
@@ -704,6 +726,7 @@ impl<O: MaybeOffset> DateTime<O> {
})
}
+ #[must_use = "this does not modify the original value"]
pub const fn replace_hour(self, hour: u8) -> Result<Self, error::ComponentRange> {
Ok(Self {
date: self.date,
@@ -712,6 +735,7 @@ impl<O: MaybeOffset> DateTime<O> {
})
}
+ #[must_use = "this does not modify the original value"]
pub const fn replace_minute(self, minute: u8) -> Result<Self, error::ComponentRange> {
Ok(Self {
date: self.date,
@@ -720,6 +744,7 @@ impl<O: MaybeOffset> DateTime<O> {
})
}
+ #[must_use = "this does not modify the original value"]
pub const fn replace_second(self, second: u8) -> Result<Self, error::ComponentRange> {
Ok(Self {
date: self.date,
@@ -728,6 +753,7 @@ impl<O: MaybeOffset> DateTime<O> {
})
}
+ #[must_use = "this does not modify the original value"]
pub const fn replace_millisecond(
self,
millisecond: u16,
@@ -739,6 +765,7 @@ impl<O: MaybeOffset> DateTime<O> {
})
}
+ #[must_use = "this does not modify the original value"]
pub const fn replace_microsecond(
self,
microsecond: u32,
@@ -750,6 +777,7 @@ impl<O: MaybeOffset> DateTime<O> {
})
}
+ #[must_use = "this does not modify the original value"]
pub const fn replace_nanosecond(self, nanosecond: u32) -> Result<Self, error::ComponentRange> {
Ok(Self {
date: self.date,
@@ -760,6 +788,7 @@ impl<O: MaybeOffset> DateTime<O> {
// Don't gate this on just having an offset, as `ZonedDateTime` cannot be set to an arbitrary
// offset.
+ #[must_use = "this does not modify the original value"]
pub const fn replace_offset(self, offset: UtcOffset) -> DateTime<offset_kind::Fixed>
where
O: IsOffsetKindFixed,
@@ -822,7 +851,9 @@ impl<O: MaybeOffset> DateTime<O> {
}
let (year, ordinal, time) = self.to_offset_raw(UtcOffset::UTC);
- let Ok(date) = Date::from_ordinal_date(year, ordinal) else { return false };
+ let Ok(date) = Date::from_ordinal_date(year, ordinal) else {
+ return false;
+ };
time.hour() == 23
&& time.minute() == 59
@@ -1156,7 +1187,7 @@ impl From<DateTime<offset_kind::Fixed>> for SystemTime {
impl From<js_sys::Date> for DateTime<offset_kind::Fixed> {
fn from(js_date: js_sys::Date) -> Self {
// get_time() returns milliseconds
- let timestamp_nanos = (js_date.get_time() * Nanosecond.per(Millisecond) as f64) as i128;
+ let timestamp_nanos = (js_date.get_time() * Nanosecond::per(Millisecond) as f64) as i128;
Self::from_unix_timestamp_nanos(timestamp_nanos)
.expect("invalid timestamp: Timestamp cannot fit in range")
}
@@ -1171,7 +1202,7 @@ impl From<DateTime<offset_kind::Fixed>> for js_sys::Date {
fn from(datetime: DateTime<offset_kind::Fixed>) -> Self {
// new Date() takes milliseconds
let timestamp =
- (datetime.unix_timestamp_nanos() / Nanosecond.per(Millisecond) as i128) as f64;
+ (datetime.unix_timestamp_nanos() / Nanosecond::per(Millisecond) as i128) as f64;
js_sys::Date::new(&timestamp.into())
}
}