Skip to content

Commit

Permalink
Move Add and Sub impls for Fixedoffset to their output type mod…
Browse files Browse the repository at this point in the history
…ules
  • Loading branch information
pitdicker committed May 23, 2023
1 parent 3a6807b commit d1b9ad7
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 74 deletions.
28 changes: 28 additions & 0 deletions src/datetime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,25 @@ impl<Tz: TimeZone> AddAssign<OldDuration> for DateTime<Tz> {
}
}

fn add_with_leapsecond<T>(lhs: &T, rhs: i32) -> T
where
T: Timelike + Add<OldDuration, Output = T>,
{
// 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<Tz: TimeZone> Add<FixedOffset> for DateTime<Tz> {
type Output = DateTime<Tz>;

#[inline]
fn add(self, rhs: FixedOffset) -> DateTime<Tz> {
add_with_leapsecond(&self, rhs.local_minus_utc())
}
}

impl<Tz: TimeZone> Add<Months> for DateTime<Tz> {
type Output = DateTime<Tz>;

Expand Down Expand Up @@ -1034,6 +1053,15 @@ impl<Tz: TimeZone> SubAssign<OldDuration> for DateTime<Tz> {
}
}

impl<Tz: TimeZone> Sub<FixedOffset> for DateTime<Tz> {
type Output = DateTime<Tz>;

#[inline]
fn sub(self, rhs: FixedOffset) -> DateTime<Tz> {
add_with_leapsecond(&self, -rhs.local_minus_utc())
}
}

impl<Tz: TimeZone> Sub<Months> for DateTime<Tz> {
type Output = DateTime<Tz>;

Expand Down
18 changes: 18 additions & 0 deletions src/naive/datetime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,15 @@ impl AddAssign<OldDuration> for NaiveDateTime {
}
}

impl Add<FixedOffset> for NaiveDateTime {
type Output = NaiveDateTime;

#[inline]
fn add(self, rhs: FixedOffset) -> NaiveDateTime {
self.checked_add_offset(rhs).unwrap()
}
}

impl Add<Months> for NaiveDateTime {
type Output = NaiveDateTime;

Expand Down Expand Up @@ -1613,6 +1622,15 @@ impl SubAssign<OldDuration> for NaiveDateTime {
}
}

impl Sub<FixedOffset> for NaiveDateTime {
type Output = NaiveDateTime;

#[inline]
fn sub(self, rhs: FixedOffset) -> NaiveDateTime {
self.checked_sub_offset(rhs).unwrap()
}
}

/// A subtraction of Months from `NaiveDateTime` clamped to valid days in resulting month.
///
/// # Panics
Expand Down
18 changes: 18 additions & 0 deletions src/naive/time/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,15 @@ impl AddAssign<OldDuration> for NaiveTime {
}
}

impl Add<FixedOffset> for NaiveTime {
type Output = NaiveTime;

#[inline]
fn add(self, rhs: FixedOffset) -> NaiveTime {
self.overflowing_add_offset(rhs).0
}
}

/// A subtraction of `Duration` from `NaiveTime` wraps around and never overflows or underflows.
/// In particular the addition ignores integral number of days.
/// It is the same as the addition with a negated `Duration`.
Expand Down Expand Up @@ -1160,6 +1169,15 @@ impl SubAssign<OldDuration> for NaiveTime {
}
}

impl Sub<FixedOffset> for NaiveTime {
type Output = NaiveTime;

#[inline]
fn sub(self, rhs: FixedOffset) -> NaiveTime {
self.overflowing_sub_offset(rhs).0
}
}

/// Subtracts another `NaiveTime` from the current time.
/// Returns a `Duration` within +/- 1 day.
/// This does not overflow or underflow at all.
Expand Down
75 changes: 1 addition & 74 deletions src/offset/fixed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@
//! The time zone which has a fixed offset from UTC.

use core::fmt;
use core::ops::{Add, Sub};

#[cfg(feature = "rkyv")]
use rkyv::{Archive, Deserialize, Serialize};

use super::{LocalResult, Offset, TimeZone};
use crate::naive::{NaiveDate, NaiveDateTime, NaiveTime};
use crate::oldtime::Duration as OldDuration;
use crate::DateTime;
use crate::Timelike;
use crate::naive::{NaiveDate, NaiveDateTime};

/// The time zone with fixed offset, from UTC-23:59:59 to UTC+23:59:59.
///
Expand Down Expand Up @@ -169,75 +165,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<T>(lhs: &T, rhs: i32) -> T
where
T: Timelike + Add<OldDuration, Output = T>,
{
// 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<FixedOffset> for NaiveTime {
type Output = NaiveTime;

#[inline]
fn add(self, rhs: FixedOffset) -> NaiveTime {
self.overflowing_add_offset(rhs).0
}
}

impl Sub<FixedOffset> for NaiveTime {
type Output = NaiveTime;

#[inline]
fn sub(self, rhs: FixedOffset) -> NaiveTime {
self.overflowing_sub_offset(rhs).0
}
}

impl Add<FixedOffset> for NaiveDateTime {
type Output = NaiveDateTime;

#[inline]
fn add(self, rhs: FixedOffset) -> NaiveDateTime {
self.checked_add_offset(rhs).unwrap()
}
}

impl Sub<FixedOffset> for NaiveDateTime {
type Output = NaiveDateTime;

#[inline]
fn sub(self, rhs: FixedOffset) -> NaiveDateTime {
self.checked_sub_offset(rhs).unwrap()
}
}

impl<Tz: TimeZone> Add<FixedOffset> for DateTime<Tz> {
type Output = DateTime<Tz>;

#[inline]
fn add(self, rhs: FixedOffset) -> DateTime<Tz> {
add_with_leapsecond(&self, rhs.local_minus_utc)
}
}

impl<Tz: TimeZone> Sub<FixedOffset> for DateTime<Tz> {
type Output = DateTime<Tz>;

#[inline]
fn sub(self, rhs: FixedOffset) -> DateTime<Tz> {
add_with_leapsecond(&self, -rhs.local_minus_utc)
}
}

#[cfg(test)]
mod tests {
use super::FixedOffset;
Expand Down

0 comments on commit d1b9ad7

Please sign in to comment.