From 225cfaaa88b3e72d0ef9e27220e64d7b2b7817b6 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Fri, 19 May 2023 14:51:22 +0200 Subject: [PATCH 1/2] Move `Add` and `Sub` impls for `Fixedoffset` to `datetime` modules --- src/datetime/mod.rs | 28 ++++++++++++++++++++++++++++ src/offset/fixed.rs | 38 +------------------------------------- 2 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index d0e63d5732..b6fbb823b0 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 013f822479..6d3aebdb68 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; From 018be06145db22c727865d7ce5dc97dd2af15fa5 Mon Sep 17 00:00:00 2001 From: Paul Dicker Date: Fri, 19 May 2023 14:52:26 +0200 Subject: [PATCH 2/2] Use `checked_(add|sub)_offset` in `Add` and `Sub` impls of `DateTime` --- src/datetime/mod.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index b6fbb823b0..59178743dc 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -1247,22 +1247,13 @@ 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()) + fn add(mut self, rhs: FixedOffset) -> DateTime { + self.datetime = self.naive_utc().checked_add_offset(rhs).unwrap(); + self } } @@ -1317,8 +1308,9 @@ impl Sub for DateTime { type Output = DateTime; #[inline] - fn sub(self, rhs: FixedOffset) -> DateTime { - add_with_leapsecond(&self, -rhs.local_minus_utc()) + fn sub(mut self, rhs: FixedOffset) -> DateTime { + self.datetime = self.naive_utc().checked_sub_offset(rhs).unwrap(); + self } }