diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index d0e63d57..b6fbb823 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -1247,6 +1247,25 @@ impl AddAssign for DateTime { } } +fn add_with_leapsecond(lhs: &T, rhs: i32) -> T +where + T: Timelike + Add, +{ + // extract and temporarily remove the fractional part and later recover it + let nanos = lhs.nanosecond(); + let lhs = lhs.with_nanosecond(0).unwrap(); + (lhs + OldDuration::seconds(i64::from(rhs))).with_nanosecond(nanos).unwrap() +} + +impl Add for DateTime { + type Output = DateTime; + + #[inline] + fn add(self, rhs: FixedOffset) -> DateTime { + add_with_leapsecond(&self, rhs.local_minus_utc()) + } +} + impl Add for DateTime { type Output = DateTime; @@ -1294,6 +1313,15 @@ impl SubAssign for DateTime { } } +impl Sub for DateTime { + type Output = DateTime; + + #[inline] + fn sub(self, rhs: FixedOffset) -> DateTime { + add_with_leapsecond(&self, -rhs.local_minus_utc()) + } +} + impl Sub for DateTime { type Output = DateTime; diff --git a/src/offset/fixed.rs b/src/offset/fixed.rs index 013f8224..6d3aebdb 100644 --- a/src/offset/fixed.rs +++ b/src/offset/fixed.rs @@ -4,17 +4,14 @@ //! The time zone which has a fixed offset from UTC. use core::fmt; -use core::ops::{Add, Sub}; use core::str::FromStr; #[cfg(feature = "rkyv")] use rkyv::{Archive, Deserialize, Serialize}; use super::{LocalResult, Offset, TimeZone}; -use crate::duration::Duration as OldDuration; -use crate::format::{scan, OUT_OF_RANGE}; +use crate::format::{scan, ParseError, OUT_OF_RANGE}; use crate::naive::{NaiveDate, NaiveDateTime}; -use crate::{DateTime, ParseError, Timelike}; /// The time zone with fixed offset, from UTC-23:59:59 to UTC+23:59:59. /// @@ -184,39 +181,6 @@ impl arbitrary::Arbitrary<'_> for FixedOffset { } } -// addition or subtraction of FixedOffset to/from Timelike values is the same as -// adding or subtracting the offset's local_minus_utc value -// but keep keeps the leap second information. -// this should be implemented more efficiently, but for the time being, this is generic right now. - -fn add_with_leapsecond(lhs: &T, rhs: i32) -> T -where - T: Timelike + Add, -{ - // extract and temporarily remove the fractional part and later recover it - let nanos = lhs.nanosecond(); - let lhs = lhs.with_nanosecond(0).unwrap(); - (lhs + OldDuration::seconds(i64::from(rhs))).with_nanosecond(nanos).unwrap() -} - -impl Add for DateTime { - type Output = DateTime; - - #[inline] - fn add(self, rhs: FixedOffset) -> DateTime { - add_with_leapsecond(&self, rhs.local_minus_utc) - } -} - -impl Sub for DateTime { - type Output = DateTime; - - #[inline] - fn sub(self, rhs: FixedOffset) -> DateTime { - add_with_leapsecond(&self, -rhs.local_minus_utc) - } -} - #[cfg(test)] mod tests { use super::FixedOffset;