From d70a36460fa649c9d49d5fb987eb4742de66008a Mon Sep 17 00:00:00 2001 From: yottalogical Date: Mon, 26 Dec 2022 13:51:24 -0500 Subject: [PATCH 1/6] Implement generic assign operations for various types Includes: * `oldtime::Duration` * `datetime::DateTime` * `naive::date::NaiveDate` * `naive::datetime::NaiveDateTime` * `naive::time::NaiveTime` Did not implement it for `date::Date`. This is because `Add` expects to be passed the owned object, but `AddAssign` only has access to a mutable reference. Since `Date` doesn't implement `Copy`, that makes it impossible to generically and safely implement `AddAssign` using `Add` without cloning. It might be possible with unsafe code, but that's probably over the top. `date::Date` is deprecated anyways. --- src/datetime/mod.rs | 44 +++++++++++++++++++++------------------ src/naive/date.rs | 34 +++++++++++++++++------------- src/naive/datetime/mod.rs | 34 +++++++++++++++++------------- src/naive/time/mod.rs | 34 +++++++++++++++++------------- src/oldtime.rs | 38 ++++++++++++++++++++++++++++++++- 5 files changed, 121 insertions(+), 63 deletions(-) diff --git a/src/datetime/mod.rs b/src/datetime/mod.rs index 05d0458e84..a3ab67a181 100644 --- a/src/datetime/mod.rs +++ b/src/datetime/mod.rs @@ -912,16 +912,6 @@ impl Add for DateTime { } } -impl AddAssign for DateTime { - #[inline] - fn add_assign(&mut self, rhs: OldDuration) { - let datetime = - self.datetime.checked_add_signed(rhs).expect("`DateTime + Duration` overflowed"); - let tz = self.timezone(); - *self = tz.from_utc_datetime(&datetime); - } -} - impl Add for DateTime { type Output = DateTime; @@ -939,16 +929,6 @@ impl Sub for DateTime { } } -impl SubAssign for DateTime { - #[inline] - fn sub_assign(&mut self, rhs: OldDuration) { - let datetime = - self.datetime.checked_sub_signed(rhs).expect("`DateTime - Duration` overflowed"); - let tz = self.timezone(); - *self = tz.from_utc_datetime(&datetime) - } -} - impl Sub for DateTime { type Output = DateTime; @@ -982,6 +962,30 @@ impl Sub for DateTime { } } +impl AddAssign for DateTime +where + NaiveDateTime: Add, +{ + #[inline] + fn add_assign(&mut self, rhs: T) { + let datetime = self.datetime + rhs; + let tz = self.timezone(); + *self = tz.from_utc_datetime(&datetime); + } +} + +impl SubAssign for DateTime +where + NaiveDateTime: Sub, +{ + #[inline] + fn sub_assign(&mut self, rhs: T) { + let datetime = self.datetime - rhs; + let tz = self.timezone(); + *self = tz.from_utc_datetime(&datetime); + } +} + impl fmt::Debug for DateTime { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.naive_local().fmt(f)?; diff --git a/src/naive/date.rs b/src/naive/date.rs index 3734460713..a33d718d35 100644 --- a/src/naive/date.rs +++ b/src/naive/date.rs @@ -1627,13 +1627,6 @@ impl Add for NaiveDate { } } -impl AddAssign for NaiveDate { - #[inline] - fn add_assign(&mut self, rhs: OldDuration) { - *self = self.add(rhs); - } -} - impl Add for NaiveDate { type Output = NaiveDate; @@ -1735,13 +1728,6 @@ impl Sub for NaiveDate { } } -impl SubAssign for NaiveDate { - #[inline] - fn sub_assign(&mut self, rhs: OldDuration) { - *self = self.sub(rhs); - } -} - /// Subtracts another `NaiveDate` from the current date. /// Returns a `Duration` of integral numbers. /// @@ -1775,6 +1761,26 @@ impl Sub for NaiveDate { } } +impl AddAssign for NaiveDate +where + Self: Add, +{ + #[inline] + fn add_assign(&mut self, rhs: T) { + *self = *self + rhs; + } +} + +impl SubAssign for NaiveDate +where + Self: Sub, +{ + #[inline] + fn sub_assign(&mut self, rhs: T) { + *self = *self - rhs; + } +} + /// Iterator over `NaiveDate` with a step size of one day. #[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord)] pub struct NaiveDateDaysIterator { diff --git a/src/naive/datetime/mod.rs b/src/naive/datetime/mod.rs index c34813f10b..250f1bfb07 100644 --- a/src/naive/datetime/mod.rs +++ b/src/naive/datetime/mod.rs @@ -1461,13 +1461,6 @@ impl Add for NaiveDateTime { } } -impl AddAssign for NaiveDateTime { - #[inline] - fn add_assign(&mut self, rhs: OldDuration) { - *self = self.add(rhs); - } -} - impl Add for NaiveDateTime { type Output = NaiveDateTime; @@ -1570,13 +1563,6 @@ impl Sub for NaiveDateTime { } } -impl SubAssign for NaiveDateTime { - #[inline] - fn sub_assign(&mut self, rhs: OldDuration) { - *self = self.sub(rhs); - } -} - /// A subtraction of Months from `NaiveDateTime` clamped to valid days in resulting month. /// /// # Panics @@ -1674,6 +1660,26 @@ impl Sub for NaiveDateTime { } } +impl AddAssign for NaiveDateTime +where + Self: Add, +{ + #[inline] + fn add_assign(&mut self, rhs: T) { + *self = *self + rhs; + } +} + +impl SubAssign for NaiveDateTime +where + Self: Sub, +{ + #[inline] + fn sub_assign(&mut self, rhs: T) { + *self = *self - rhs; + } +} + /// The `Debug` output of the naive date and time `dt` is the same as /// [`dt.format("%Y-%m-%dT%H:%M:%S%.f")`](crate::format::strftime). /// diff --git a/src/naive/time/mod.rs b/src/naive/time/mod.rs index 1d36583aa2..a3ca7de077 100644 --- a/src/naive/time/mod.rs +++ b/src/naive/time/mod.rs @@ -1024,13 +1024,6 @@ impl Add for NaiveTime { } } -impl AddAssign for NaiveTime { - #[inline] - fn add_assign(&mut self, rhs: OldDuration) { - *self = self.add(rhs); - } -} - /// 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`. @@ -1085,13 +1078,6 @@ impl Sub for NaiveTime { } } -impl SubAssign for NaiveTime { - #[inline] - fn sub_assign(&mut self, rhs: OldDuration) { - *self = self.sub(rhs); - } -} - /// Subtracts another `NaiveTime` from the current time. /// Returns a `Duration` within +/- 1 day. /// This does not overflow or underflow at all. @@ -1146,6 +1132,26 @@ impl Sub for NaiveTime { } } +impl AddAssign for NaiveTime +where + Self: Add, +{ + #[inline] + fn add_assign(&mut self, rhs: T) { + *self = *self + rhs; + } +} + +impl SubAssign for NaiveTime +where + Self: Sub, +{ + #[inline] + fn sub_assign(&mut self, rhs: T) { + *self = *self - rhs; + } +} + /// The `Debug` output of the naive time `t` is the same as /// [`t.format("%H:%M:%S%.f")`](../format/strftime/index.html). /// diff --git a/src/oldtime.rs b/src/oldtime.rs index f935e9a4b1..1d50e61bfe 100644 --- a/src/oldtime.rs +++ b/src/oldtime.rs @@ -10,7 +10,7 @@ //! Temporal quantification -use core::ops::{Add, Div, Mul, Neg, Sub}; +use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use core::time::Duration as StdDuration; use core::{fmt, i64}; #[cfg(any(feature = "std", test))] @@ -381,6 +381,42 @@ impl Div for Duration { } } +impl AddAssign for Duration +where + Self: Add, +{ + fn add_assign(&mut self, rhs: T) { + *self = *self + rhs; + } +} + +impl SubAssign for Duration +where + Self: Sub, +{ + fn sub_assign(&mut self, rhs: T) { + *self = *self - rhs; + } +} + +impl MulAssign for Duration +where + Self: Mul, +{ + fn mul_assign(&mut self, rhs: T) { + *self = *self * rhs; + } +} + +impl DivAssign for Duration +where + Self: Div, +{ + fn div_assign(&mut self, rhs: T) { + *self = *self / rhs; + } +} + #[cfg(any(feature = "std", test))] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl<'a> std::iter::Sum<&'a Duration> for Duration { From 6c2f3584af15b285fe7ea03b0483f48a14ac001c Mon Sep 17 00:00:00 2001 From: yottalogical Date: Mon, 26 Dec 2022 14:54:19 -0500 Subject: [PATCH 2/6] Add tests for Duration assign ops --- src/oldtime.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/oldtime.rs b/src/oldtime.rs index 1d50e61bfe..03ba6c4366 100644 --- a/src/oldtime.rs +++ b/src/oldtime.rs @@ -722,6 +722,78 @@ mod tests { assert_eq!(Duration::seconds(-4) / -3, Duration::nanoseconds(1_333_333_333)); } + #[test] + fn test_duration_addassign() { + let mut dur = Duration::zero(); + dur += Duration::zero(); + assert_eq!(dur, Duration::zero()); + dur += Duration::seconds(1); + assert_eq!(dur, Duration::seconds(1)); + dur += Duration::minutes(2); + assert_eq!(dur, Duration::seconds(121)); + dur += Duration::seconds(-42); + assert_eq!(dur, Duration::seconds(79)); + } + + #[test] + fn test_duration_subassign() { + let mut dur = Duration::minutes(5); + dur -= Duration::zero(); + assert_eq!(dur, Duration::minutes(5)); + dur -= Duration::seconds(1); + assert_eq!(dur, Duration::seconds(299)); + dur -= Duration::minutes(10); + assert_eq!(dur, Duration::seconds(-301)); + dur -= Duration::seconds(-42); + assert_eq!(dur, Duration::seconds(-259)); + } + + #[test] + fn test_duration_mulassign() { + { + let mut dur = Duration::zero(); + dur *= 2; + assert_eq!(dur, Duration::zero()); + dur *= 0; + assert_eq!(dur, Duration::zero()); + } + + { + let mut dur = Duration::minutes(1); + dur *= 2; + assert_eq!(dur, Duration::minutes(2)); + dur *= 1; + assert_eq!(dur, Duration::minutes(2)); + dur *= -3; + assert_eq!(dur, Duration::minutes(-6)); + dur *= -1; + assert_eq!(dur, Duration::minutes(6)); + dur *= 0; + assert_eq!(dur, Duration::zero()); + } + } + + #[test] + fn test_duration_divassign() { + { + let mut dur = Duration::zero(); + dur /= 2; + assert_eq!(dur, Duration::zero()); + dur /= -3; + assert_eq!(dur, Duration::zero()); + } + + { + let mut dur = Duration::minutes(10); + dur /= 2; + assert_eq!(dur, Duration::minutes(5)); + dur /= 2; + assert_eq!(dur, Duration::seconds(150)); + dur /= -3; + assert_eq!(dur, Duration::seconds(-50)); + } + } + #[test] fn test_duration_sum() { let duration_list_1 = [Duration::zero(), Duration::seconds(1)]; From 47e862941f0b9e8e098566d03612007c7261681f Mon Sep 17 00:00:00 2001 From: yottalogical Date: Sat, 7 Jan 2023 16:45:45 -0500 Subject: [PATCH 3/6] Add tests for DateTime assign ops --- src/datetime/tests.rs | 67 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/datetime/tests.rs b/src/datetime/tests.rs index ebd32cae93..f066e97dbf 100644 --- a/src/datetime/tests.rs +++ b/src/datetime/tests.rs @@ -242,6 +242,73 @@ fn test_datetime_sub_months() { ); } +#[test] +fn test_datetime_addassign() { + let est = FixedOffset::west_opt(5 * 60 * 60).unwrap(); + let original_dt = est.with_ymd_and_hms(2014, 5, 6, 7, 8, 9).unwrap(); + + { + let mut dt = original_dt; + dt += Duration::seconds(5); + assert_eq!(dt, original_dt + Duration::seconds(5)); + dt += Duration::minutes(35); + assert_eq!(dt, original_dt + Duration::seconds(2105)); + } + + { + let mut dt = original_dt; + dt += Days::new(5); + assert_eq!(dt, original_dt + Days::new(5)); + dt += Days::new(35); + assert_eq!(dt, original_dt + Days::new(40)); + } + + { + let mut dt = original_dt; + dt += Months::new(1); + assert_eq!(dt, original_dt + Months::new(1)); + dt += Months::new(5); + assert_eq!(dt, original_dt + Months::new(6)); + } +} + +#[test] +fn test_datetime_subassign() { + let est = FixedOffset::west_opt(5 * 60 * 60).unwrap(); + let original_dt = est.with_ymd_and_hms(2014, 5, 6, 7, 8, 9).unwrap(); + + { + let mut dt = original_dt; + dt -= Duration::seconds(5); + assert_eq!(dt, original_dt - Duration::seconds(5)); + dt -= Duration::minutes(35); + assert_eq!(dt, original_dt - Duration::seconds(2105)); + } + + { + let mut dt = original_dt; + dt -= Days::new(5); + assert_eq!(dt, original_dt - Days::new(5)); + dt -= Days::new(35); + assert_eq!(dt, original_dt - Days::new(40)); + } + + { + let mut dt = original_dt; + dt -= Months::new(1); + assert_eq!(dt, original_dt - Months::new(1)); + dt -= Months::new(5); + assert_eq!(dt, original_dt - Months::new(6)); + } +} + +#[test] +#[should_panic(expected = "`NaiveDateTime + Duration` overflowed")] +fn test_datetime_addassign_overflow() { + let mut dt = DateTime::::MAX_UTC; + dt += Duration::seconds(1); +} + #[test] fn test_datetime_offset() { let est = FixedOffset::west_opt(5 * 60 * 60).unwrap(); From 4ff6a62df75ee03b5f891fe225ba06fae88f5e54 Mon Sep 17 00:00:00 2001 From: yottalogical Date: Sat, 7 Jan 2023 16:58:24 -0500 Subject: [PATCH 4/6] Add tests for NaiveDate assign ops --- src/datetime/tests.rs | 4 +-- src/naive/date.rs | 58 +++++++++++++++++++++++++++++++++++-------- src/oldtime.rs | 4 +-- 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/datetime/tests.rs b/src/datetime/tests.rs index f066e97dbf..dd4f5ef81e 100644 --- a/src/datetime/tests.rs +++ b/src/datetime/tests.rs @@ -243,7 +243,7 @@ fn test_datetime_sub_months() { } #[test] -fn test_datetime_addassign() { +fn test_datetime_addassignment() { let est = FixedOffset::west_opt(5 * 60 * 60).unwrap(); let original_dt = est.with_ymd_and_hms(2014, 5, 6, 7, 8, 9).unwrap(); @@ -273,7 +273,7 @@ fn test_datetime_addassign() { } #[test] -fn test_datetime_subassign() { +fn test_datetime_subassignment() { let est = FixedOffset::west_opt(5 * 60 * 60).unwrap(); let original_dt = est.with_ymd_and_hms(2014, 5, 6, 7, 8, 9).unwrap(); diff --git a/src/naive/date.rs b/src/naive/date.rs index a33d718d35..072c7787a4 100644 --- a/src/naive/date.rs +++ b/src/naive/date.rs @@ -2719,21 +2719,59 @@ mod tests { #[test] fn test_date_addassignment() { let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap(); - let mut date = ymd(2016, 10, 1); - date += Duration::days(10); - assert_eq!(date, ymd(2016, 10, 11)); - date += Duration::days(30); - assert_eq!(date, ymd(2016, 11, 10)); + + { + let mut date = ymd(2016, 10, 1); + date += Duration::days(10); + assert_eq!(date, ymd(2016, 10, 11)); + date += Duration::days(30); + assert_eq!(date, ymd(2016, 11, 10)); + } + + { + let mut date = ymd(2016, 10, 1); + date += Months::new(1); + assert_eq!(date, ymd(2016, 11, 1)); + date += Months::new(3); + assert_eq!(date, ymd(2017, 2, 1)); + } + + { + let mut date = ymd(2016, 10, 1); + date += Days::new(10); + assert_eq!(date, ymd(2016, 10, 11)); + date += Days::new(30); + assert_eq!(date, ymd(2016, 11, 10)); + } } #[test] fn test_date_subassignment() { let ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap(); - let mut date = ymd(2016, 10, 11); - date -= Duration::days(10); - assert_eq!(date, ymd(2016, 10, 1)); - date -= Duration::days(2); - assert_eq!(date, ymd(2016, 9, 29)); + + { + let mut date = ymd(2016, 10, 11); + date -= Duration::days(10); + assert_eq!(date, ymd(2016, 10, 1)); + date -= Duration::days(2); + assert_eq!(date, ymd(2016, 9, 29)); + } + + { + let mut date = ymd(2016, 10, 11); + date -= Months::new(10); + assert_eq!(date, ymd(2015, 12, 11)); + date -= Months::new(2); + assert_eq!(date, ymd(2015, 10, 11)); + } + + { + let mut date = ymd(2016, 10, 11); + date -= Days::new(10); + assert_eq!(date, ymd(2016, 10, 1)); + date -= Days::new(2); + assert_eq!(date, ymd(2016, 9, 29)); + } } #[test] diff --git a/src/oldtime.rs b/src/oldtime.rs index 03ba6c4366..72bf93e129 100644 --- a/src/oldtime.rs +++ b/src/oldtime.rs @@ -723,7 +723,7 @@ mod tests { } #[test] - fn test_duration_addassign() { + fn test_duration_addassignment() { let mut dur = Duration::zero(); dur += Duration::zero(); assert_eq!(dur, Duration::zero()); @@ -736,7 +736,7 @@ mod tests { } #[test] - fn test_duration_subassign() { + fn test_duration_subassignment() { let mut dur = Duration::minutes(5); dur -= Duration::zero(); assert_eq!(dur, Duration::minutes(5)); From 048237bcf85054c819ff4f4f063c9f58007acc16 Mon Sep 17 00:00:00 2001 From: yottalogical Date: Sat, 7 Jan 2023 17:13:41 -0500 Subject: [PATCH 5/6] Add tests for NaiveDateTime assign ops --- src/naive/datetime/tests.rs | 62 +++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/src/naive/datetime/tests.rs b/src/naive/datetime/tests.rs index 202bdb34d3..c8ba14206e 100644 --- a/src/naive/datetime/tests.rs +++ b/src/naive/datetime/tests.rs @@ -1,7 +1,5 @@ use super::NaiveDateTime; -use crate::oldtime::Duration; -use crate::NaiveDate; -use crate::{Datelike, FixedOffset, Utc}; +use crate::{oldtime::Duration, Datelike, Days, FixedOffset, Months, NaiveDate, Utc}; use std::i64; #[test] @@ -163,22 +161,60 @@ fn test_datetime_sub() { fn test_datetime_addassignment() { let ymdhms = |y, m, d, h, n, s| NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap(); - let mut date = ymdhms(2016, 10, 1, 10, 10, 10); - date += Duration::minutes(10_000_000); - assert_eq!(date, ymdhms(2035, 10, 6, 20, 50, 10)); - date += Duration::days(10); - assert_eq!(date, ymdhms(2035, 10, 16, 20, 50, 10)); + + { + let mut date = ymdhms(2016, 10, 1, 10, 10, 10); + date += Duration::minutes(10_000_000); + assert_eq!(date, ymdhms(2035, 10, 6, 20, 50, 10)); + date += Duration::days(10); + assert_eq!(date, ymdhms(2035, 10, 16, 20, 50, 10)); + } + + { + let mut date = ymdhms(2016, 10, 1, 10, 10, 10); + date += Months::new(1_000); + assert_eq!(date, ymdhms(2100, 2, 1, 10, 10, 10)); + date += Months::new(10); + assert_eq!(date, ymdhms(2100, 12, 1, 10, 10, 10)); + } + + { + let mut date = ymdhms(2016, 10, 1, 10, 10, 10); + date += Days::new(10_000); + assert_eq!(date, ymdhms(2044, 2, 17, 10, 10, 10)); + date += Days::new(10); + assert_eq!(date, ymdhms(2044, 2, 27, 10, 10, 10)); + } } #[test] fn test_datetime_subassignment() { let ymdhms = |y, m, d, h, n, s| NaiveDate::from_ymd_opt(y, m, d).unwrap().and_hms_opt(h, n, s).unwrap(); - let mut date = ymdhms(2016, 10, 1, 10, 10, 10); - date -= Duration::minutes(10_000_000); - assert_eq!(date, ymdhms(1997, 9, 26, 23, 30, 10)); - date -= Duration::days(10); - assert_eq!(date, ymdhms(1997, 9, 16, 23, 30, 10)); + + { + let mut date = ymdhms(2016, 10, 1, 10, 10, 10); + date -= Duration::minutes(10_000_000); + assert_eq!(date, ymdhms(1997, 9, 26, 23, 30, 10)); + date -= Duration::days(10); + assert_eq!(date, ymdhms(1997, 9, 16, 23, 30, 10)); + } + + { + let mut date = ymdhms(2016, 10, 1, 10, 10, 10); + date -= Months::new(1_000); + assert_eq!(date, ymdhms(1933, 6, 1, 10, 10, 10)); + date -= Months::new(10); + assert_eq!(date, ymdhms(1932, 8, 1, 10, 10, 10)); + } + + { + let mut date = ymdhms(2016, 10, 1, 10, 10, 10); + date -= Days::new(10_000); + assert_eq!(date, ymdhms(1989, 5, 16, 10, 10, 10)); + date -= Days::new(10); + assert_eq!(date, ymdhms(1989, 5, 6, 10, 10, 10)); + } } #[test] From 3e1161b8e0f501da090e87015836d05150ee72cd Mon Sep 17 00:00:00 2001 From: yottalogical Date: Sat, 7 Jan 2023 17:27:39 -0500 Subject: [PATCH 6/6] Follow the more standard test format for DateTime tests --- src/datetime/tests.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/datetime/tests.rs b/src/datetime/tests.rs index dd4f5ef81e..41cca36079 100644 --- a/src/datetime/tests.rs +++ b/src/datetime/tests.rs @@ -245,30 +245,30 @@ fn test_datetime_sub_months() { #[test] fn test_datetime_addassignment() { let est = FixedOffset::west_opt(5 * 60 * 60).unwrap(); - let original_dt = est.with_ymd_and_hms(2014, 5, 6, 7, 8, 9).unwrap(); + let ymdhms = |y, m, d, h, n, s| est.with_ymd_and_hms(y, m, d, h, n, s).unwrap(); { - let mut dt = original_dt; + let mut dt = ymdhms(2014, 5, 6, 7, 8, 9); dt += Duration::seconds(5); - assert_eq!(dt, original_dt + Duration::seconds(5)); + assert_eq!(dt, ymdhms(2014, 5, 6, 7, 8, 14)); dt += Duration::minutes(35); - assert_eq!(dt, original_dt + Duration::seconds(2105)); + assert_eq!(dt, ymdhms(2014, 5, 6, 7, 43, 14)); } { - let mut dt = original_dt; + let mut dt = ymdhms(2014, 5, 6, 7, 8, 9); dt += Days::new(5); - assert_eq!(dt, original_dt + Days::new(5)); + assert_eq!(dt, ymdhms(2014, 5, 11, 7, 8, 9)); dt += Days::new(35); - assert_eq!(dt, original_dt + Days::new(40)); + assert_eq!(dt, ymdhms(2014, 6, 15, 7, 8, 9)); } { - let mut dt = original_dt; + let mut dt = ymdhms(2014, 5, 6, 7, 8, 9); dt += Months::new(1); - assert_eq!(dt, original_dt + Months::new(1)); + assert_eq!(dt, ymdhms(2014, 6, 6, 7, 8, 9)); dt += Months::new(5); - assert_eq!(dt, original_dt + Months::new(6)); + assert_eq!(dt, ymdhms(2014, 11, 6, 7, 8, 9)); } }