From 22085075374ceeb4bc23a53f7a01a83f5b254f66 Mon Sep 17 00:00:00 2001 From: tushushu Date: Mon, 11 Oct 2021 21:19:43 +0800 Subject: [PATCH 01/30] fix Timestamp + Dateoffset bugs. --- pandas/_libs/tslibs/offsets.pxd | 1 + pandas/_libs/tslibs/offsets.pyx | 4 ++++ pandas/_libs/tslibs/timestamps.pyx | 7 +++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pxd b/pandas/_libs/tslibs/offsets.pxd index 215c3f849281f..f02a7eea8ab15 100644 --- a/pandas/_libs/tslibs/offsets.pxd +++ b/pandas/_libs/tslibs/offsets.pxd @@ -2,6 +2,7 @@ from numpy cimport int64_t cpdef to_offset(object obj) +cdef bint is_dateoffset_object(object obj) cdef bint is_offset_object(object obj) cdef bint is_tick_object(object obj) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index ea714ce0162bc..4af6dedafadc4 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -83,6 +83,10 @@ from .timestamps import Timestamp # --------------------------------------------------------------------- # Misc Helpers +cdef bint is_dateoffset_object(object obj): + return isinstance(obj, DateOffset) + + cdef bint is_offset_object(object obj): return isinstance(obj, BaseOffset) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 613da5a691736..2167bc4a9043f 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -83,6 +83,7 @@ from pandas._libs.tslibs.np_datetime cimport ( from pandas._libs.tslibs.np_datetime import OutOfBoundsDatetime from pandas._libs.tslibs.offsets cimport ( + is_dateoffset_object, is_offset_object, to_offset, ) @@ -283,8 +284,11 @@ cdef class _Timestamp(ABCTimestamp): cdef: int64_t nanos = 0 + if is_dateoffset_object(other): + nanos += other.nanoseconds + other = other._offset if is_any_td_scalar(other): - nanos = delta_to_nanoseconds(other) + nanos += delta_to_nanoseconds(other) result = type(self)(self.value + nanos, tz=self.tzinfo) if result is not NaT: result._set_freq(self._freq) # avoid warning in constructor @@ -307,7 +311,6 @@ cdef class _Timestamp(ABCTimestamp): elif not isinstance(self, _Timestamp): # cython semantics, args have been switched and this is __radd__ return other.__add__(self) - return NotImplemented def __sub__(self, other): From ee19a4dad768f6f3066a3f60462d4d240f3ca588 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sat, 16 Oct 2021 12:24:57 +0800 Subject: [PATCH 02/30] Add doc string and fix UT. --- pandas/_libs/tslibs/offsets.pyx | 4 +++- pandas/_libs/tslibs/timestamps.pyx | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 4af6dedafadc4..25c09fd46fbfd 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -84,7 +84,9 @@ from .timestamps import Timestamp # Misc Helpers cdef bint is_dateoffset_object(object obj): - return isinstance(obj, DateOffset) + # Note: This is to fix Timestamp __add__/__sub__ DateOffset with + # nanoseconds lost. See PR #43968 + return type(obj) is DateOffset cdef bint is_offset_object(object obj): diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 2167bc4a9043f..117405ada1f4b 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -283,7 +283,7 @@ cdef class _Timestamp(ABCTimestamp): def __add__(self, other): cdef: int64_t nanos = 0 - + if is_dateoffset_object(other): nanos += other.nanoseconds other = other._offset From 3e38ab24b327b814d16da7b975c032c37b2ab897 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sat, 16 Oct 2021 13:47:00 +0800 Subject: [PATCH 03/30] fix UT --- pandas/_libs/tslibs/timestamps.pyx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 117405ada1f4b..519082e92e12d 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -285,8 +285,9 @@ cdef class _Timestamp(ABCTimestamp): int64_t nanos = 0 if is_dateoffset_object(other): - nanos += other.nanoseconds - other = other._offset + if hasattr(other, "nanoseconds"): + nanos += other.nanoseconds + other = other._offset if is_any_td_scalar(other): nanos += delta_to_nanoseconds(other) result = type(self)(self.value + nanos, tz=self.tzinfo) From 5718e4fd289e428a8fc3406a1c266cec20a426c9 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sat, 16 Oct 2021 13:58:55 +0800 Subject: [PATCH 04/30] Trim Trailing Whitespace --- pandas/_libs/tslibs/timestamps.pyx | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 519082e92e12d..55d2e61852a74 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -283,7 +283,6 @@ cdef class _Timestamp(ABCTimestamp): def __add__(self, other): cdef: int64_t nanos = 0 - if is_dateoffset_object(other): if hasattr(other, "nanoseconds"): nanos += other.nanoseconds From e1ae149000d6f68bbc077c3b34a0036fdfe04bdc Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 17 Oct 2021 10:45:35 +0800 Subject: [PATCH 05/30] remove is_dateoffset_obj func --- pandas/_libs/tslibs/offsets.pxd | 1 - pandas/_libs/tslibs/offsets.pyx | 6 ------ 2 files changed, 7 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pxd b/pandas/_libs/tslibs/offsets.pxd index f02a7eea8ab15..215c3f849281f 100644 --- a/pandas/_libs/tslibs/offsets.pxd +++ b/pandas/_libs/tslibs/offsets.pxd @@ -2,7 +2,6 @@ from numpy cimport int64_t cpdef to_offset(object obj) -cdef bint is_dateoffset_object(object obj) cdef bint is_offset_object(object obj) cdef bint is_tick_object(object obj) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 25c09fd46fbfd..ea714ce0162bc 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -83,12 +83,6 @@ from .timestamps import Timestamp # --------------------------------------------------------------------- # Misc Helpers -cdef bint is_dateoffset_object(object obj): - # Note: This is to fix Timestamp __add__/__sub__ DateOffset with - # nanoseconds lost. See PR #43968 - return type(obj) is DateOffset - - cdef bint is_offset_object(object obj): return isinstance(obj, BaseOffset) From 326790bb41f9931872b53c302b939f6c95f3423b Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 17 Oct 2021 10:46:49 +0800 Subject: [PATCH 06/30] explicitly check the Offset type --- pandas/_libs/tslibs/timestamps.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 55d2e61852a74..f1acb87069516 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -83,7 +83,6 @@ from pandas._libs.tslibs.np_datetime cimport ( from pandas._libs.tslibs.np_datetime import OutOfBoundsDatetime from pandas._libs.tslibs.offsets cimport ( - is_dateoffset_object, is_offset_object, to_offset, ) @@ -283,10 +282,11 @@ cdef class _Timestamp(ABCTimestamp): def __add__(self, other): cdef: int64_t nanos = 0 - if is_dateoffset_object(other): + if is_offset_object(other): if hasattr(other, "nanoseconds"): nanos += other.nanoseconds - other = other._offset + other = other._offset + if is_any_td_scalar(other): nanos += delta_to_nanoseconds(other) result = type(self)(self.value + nanos, tz=self.tzinfo) From 83453dad06c87fcfa57c25c76b29e226c7108aa6 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 17 Oct 2021 11:03:21 +0800 Subject: [PATCH 07/30] fix bugs. --- pandas/_libs/tslibs/timestamps.pyx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index f1acb87069516..b54c8b9f12be0 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -285,7 +285,8 @@ cdef class _Timestamp(ABCTimestamp): if is_offset_object(other): if hasattr(other, "nanoseconds"): nanos += other.nanoseconds - other = other._offset + if hasattr(other, "_offset"): + other = other._offset if is_any_td_scalar(other): nanos += delta_to_nanoseconds(other) From ae4b13309cc510cb612a3e6a0b121c126bb9111b Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 17 Oct 2021 11:26:37 +0800 Subject: [PATCH 08/30] fix bugs --- pandas/_libs/tslibs/timestamps.pyx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index b54c8b9f12be0..9aa491fd41c54 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -282,11 +282,9 @@ cdef class _Timestamp(ABCTimestamp): def __add__(self, other): cdef: int64_t nanos = 0 - if is_offset_object(other): - if hasattr(other, "nanoseconds"): - nanos += other.nanoseconds - if hasattr(other, "_offset"): - other = other._offset + if is_offset_object(other) and hasattr(other, "nanoseconds"): + nanos += other.nanoseconds + other = other._offset if is_any_td_scalar(other): nanos += delta_to_nanoseconds(other) From a43030d8cd0a3f6bc12bb23be66e93dba66e1d26 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 17 Oct 2021 14:24:59 +0800 Subject: [PATCH 09/30] try to fix __sub__ method. --- pandas/_libs/tslibs/timestamps.pyx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 9aa491fd41c54..e3babe68aa193 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -283,8 +283,12 @@ cdef class _Timestamp(ABCTimestamp): cdef: int64_t nanos = 0 if is_offset_object(other) and hasattr(other, "nanoseconds"): - nanos += other.nanoseconds - other = other._offset + if other.n > 0: + nanos += other.nanoseconds + other = other._offset + else: + nanos -= other.nanoseconds + other = -other._offset if is_any_td_scalar(other): nanos += delta_to_nanoseconds(other) @@ -314,7 +318,7 @@ cdef class _Timestamp(ABCTimestamp): def __sub__(self, other): - if is_any_td_scalar(other) or is_integer_object(other): + if is_any_td_scalar(other) or is_integer_object(other) or is_offset_object(other): neg_other = -other return self + neg_other From 22cadbf17ad895f2312d5d6a48fb5bc37646fcb1 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 17 Oct 2021 17:08:33 +0800 Subject: [PATCH 10/30] fix flake8 check. --- pandas/_libs/tslibs/timestamps.pyx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index e3babe68aa193..61808c8edcdbe 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -318,7 +318,8 @@ cdef class _Timestamp(ABCTimestamp): def __sub__(self, other): - if is_any_td_scalar(other) or is_integer_object(other) or is_offset_object(other): + if (is_any_td_scalar(other) or is_integer_object(other) or + is_offset_object(other)): neg_other = -other return self + neg_other From 1c89c037c36ef0dc355dfb636eac56b5371d20e7 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 17 Oct 2021 18:49:12 +0800 Subject: [PATCH 11/30] add tests for dateoffset add method. --- pandas/tests/tseries/offsets/test_offsets.py | 37 +++++++++++++++----- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index 0c79c0b64f4cd..35aba950402b2 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -657,14 +657,6 @@ def test_rule_code(self): assert alias == (_get_offset(alias) * 5).rule_code -def test_dateoffset_misc(): - oset = offsets.DateOffset(months=2, days=4) - # it works - oset.freqstr - - assert not offsets.DateOffset(months=2) == 2 - - def test_freq_offsets(): off = BDay(1, offset=timedelta(0, 1800)) assert off.freqstr == "B+30Min" @@ -780,6 +772,27 @@ def test_tick_normalize_raises(tick_classes): cls(n=3, normalize=True) +@pytest.mark.parametrize( + "cases", + [ + ("nanoseconds", Timestamp('1970-01-01 00:00:00.000000001')), + ("microseconds", Timestamp('1970-01-01 00:00:00.000001')), + ("seconds", Timestamp('1970-01-01 00:00:01')), + ("minutes", Timestamp('1970-01-01 00:01:00')), + ("hours", Timestamp('1970-01-01 01:00:00')), + ("days", Timestamp('1970-01-02 00:00:00')), + ("weeks", Timestamp('1970-01-08 00:00:00')), + ("months", Timestamp('1970-02-01 00:00:00')), + ("years", Timestamp('1971-01-01 00:00:00')), + ], +) +def test_dateoffset_add(cases): + time_unit, expected = cases + offset = DateOffset(**{time_unit: 1}) + ts = Timestamp(0) + offset + assert ts == expected + + @pytest.mark.parametrize( "attribute", [ @@ -795,3 +808,11 @@ def test_dateoffset_immutable(attribute): msg = "DateOffset objects are immutable" with pytest.raises(AttributeError, match=msg): setattr(offset, attribute, 5) + + +def test_dateoffset_misc(): + oset = offsets.DateOffset(months=2, days=4) + # it works + oset.freqstr + + assert not offsets.DateOffset(months=2) == 2 From a2ad27458ea11f432161fc2c6aca139f9ba08a3c Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 17 Oct 2021 18:56:58 +0800 Subject: [PATCH 12/30] fix offset init. --- pandas/_libs/tslibs/offsets.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index ea714ce0162bc..c9597fa2a1a26 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -326,7 +326,7 @@ cdef _determine_offset(kwds): # sub-daily offset - use timedelta (tz-aware) offset = timedelta(**kwds_no_nanos) else: - offset = timedelta(1) + offset = timedelta(0) return offset, use_relativedelta From 9bc6e9799bb143a67abe2173e6d19e592de02ee7 Mon Sep 17 00:00:00 2001 From: tushushu Date: Mon, 18 Oct 2021 19:35:45 +0800 Subject: [PATCH 13/30] fix black code style check. --- pandas/tests/tseries/offsets/test_offsets.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index 35aba950402b2..48bd06531cd61 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -775,15 +775,15 @@ def test_tick_normalize_raises(tick_classes): @pytest.mark.parametrize( "cases", [ - ("nanoseconds", Timestamp('1970-01-01 00:00:00.000000001')), - ("microseconds", Timestamp('1970-01-01 00:00:00.000001')), - ("seconds", Timestamp('1970-01-01 00:00:01')), - ("minutes", Timestamp('1970-01-01 00:01:00')), - ("hours", Timestamp('1970-01-01 01:00:00')), - ("days", Timestamp('1970-01-02 00:00:00')), - ("weeks", Timestamp('1970-01-08 00:00:00')), - ("months", Timestamp('1970-02-01 00:00:00')), - ("years", Timestamp('1971-01-01 00:00:00')), + ("nanoseconds", Timestamp("1970-01-01 00:00:00.000000001")), + ("microseconds", Timestamp("1970-01-01 00:00:00.000001")), + ("seconds", Timestamp("1970-01-01 00:00:01")), + ("minutes", Timestamp("1970-01-01 00:01:00")), + ("hours", Timestamp("1970-01-01 01:00:00")), + ("days", Timestamp("1970-01-02 00:00:00")), + ("weeks", Timestamp("1970-01-08 00:00:00")), + ("months", Timestamp("1970-02-01 00:00:00")), + ("years", Timestamp("1971-01-01 00:00:00")), ], ) def test_dateoffset_add(cases): From c9ddf145ecab0b2faf9b560c341fbd78f487752f Mon Sep 17 00:00:00 2001 From: tushushu Date: Mon, 18 Oct 2021 19:43:01 +0800 Subject: [PATCH 14/30] test sub method. --- pandas/tests/tseries/offsets/test_offsets.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index 48bd06531cd61..d7e0320717fba 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -786,11 +786,13 @@ def test_tick_normalize_raises(tick_classes): ("years", Timestamp("1971-01-01 00:00:00")), ], ) -def test_dateoffset_add(cases): +def test_dateoffset_add_sub(cases): time_unit, expected = cases offset = DateOffset(**{time_unit: 1}) ts = Timestamp(0) + offset assert ts == expected + ts -= offset + assert ts == Timestamp(0) @pytest.mark.parametrize( From 47803168a8e3230a01154947546137c4423b8e36 Mon Sep 17 00:00:00 2001 From: tushushu Date: Tue, 19 Oct 2021 22:07:22 +0800 Subject: [PATCH 15/30] add an comment. --- pandas/_libs/tslibs/timestamps.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 61808c8edcdbe..d33a993501ca4 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -282,6 +282,7 @@ cdef class _Timestamp(ABCTimestamp): def __add__(self, other): cdef: int64_t nanos = 0 + # In order to correctly handle DateOffset object with nanoseconds. if is_offset_object(other) and hasattr(other, "nanoseconds"): if other.n > 0: nanos += other.nanoseconds From 1fecfa62b1712871f066ff80468648b1fe49c050 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sat, 23 Oct 2021 17:02:46 +0800 Subject: [PATCH 16/30] move the nano handling codes to Offsets. --- pandas/_libs/tslibs/offsets.pyx | 5 +++++ pandas/_libs/tslibs/timestamps.pyx | 8 -------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index c9597fa2a1a26..ce318f5a79d46 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -166,6 +166,11 @@ def apply_wraps(func): tz = other.tzinfo nano = other.nanosecond + if hasattr(self, "nanoseconds"): + if self.n > 0: + nano += self.nanoseconds + else: + nano -= self.nanoseconds if self._adjust_dst: other = other.tz_localize(None) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index d33a993501ca4..db25b91b3bf1a 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -282,14 +282,6 @@ cdef class _Timestamp(ABCTimestamp): def __add__(self, other): cdef: int64_t nanos = 0 - # In order to correctly handle DateOffset object with nanoseconds. - if is_offset_object(other) and hasattr(other, "nanoseconds"): - if other.n > 0: - nanos += other.nanoseconds - other = other._offset - else: - nanos -= other.nanoseconds - other = -other._offset if is_any_td_scalar(other): nanos += delta_to_nanoseconds(other) From e92c1a99bfaeb2f1bb80d684907d3a622b868f90 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sat, 23 Oct 2021 17:05:30 +0800 Subject: [PATCH 17/30] remove unnecessary codes. --- pandas/_libs/tslibs/timestamps.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index db25b91b3bf1a..bfb30ac3df530 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -284,7 +284,7 @@ cdef class _Timestamp(ABCTimestamp): int64_t nanos = 0 if is_any_td_scalar(other): - nanos += delta_to_nanoseconds(other) + nanos = delta_to_nanoseconds(other) result = type(self)(self.value + nanos, tz=self.tzinfo) if result is not NaT: result._set_freq(self._freq) # avoid warning in constructor From 006c073bf28f09a51124cf0f52c9d45c91641a6f Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 24 Oct 2021 10:42:35 +0800 Subject: [PATCH 18/30] fix bugs --- pandas/_libs/tslibs/offsets.pyx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index ce318f5a79d46..b3f250015252d 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -166,11 +166,6 @@ def apply_wraps(func): tz = other.tzinfo nano = other.nanosecond - if hasattr(self, "nanoseconds"): - if self.n > 0: - nano += self.nanoseconds - else: - nano -= self.nanoseconds if self._adjust_dst: other = other.tz_localize(None) @@ -185,7 +180,7 @@ def apply_wraps(func): result = result.normalize() # nanosecond may be deleted depending on offset process - if not self.normalize and nano != 0: + if not self.normalize and nano != 0 and not hasattr(self, "nanoseconds"): if result.nanosecond != nano: if result.tz is not None: # convert to UTC @@ -1051,12 +1046,17 @@ cdef class RelativeDeltaOffset(BaseOffset): # perform calculation in UTC other = other.replace(tzinfo=None) + if hasattr(self, "nanoseconds"): + td_nano = Timedelta(nanoseconds=self.nanoseconds) + else: + td_nano = Timedelta(0) + if self.n > 0: for i in range(self.n): - other = other + self._offset + other = other + self._offset + td_nano else: for i in range(-self.n): - other = other - self._offset + other = other - self._offset - td_nano if tzinfo is not None and self._use_relativedelta: # bring tz back from UTC calculation From ab064b42bb5e3e93378afc66db21d940478d6583 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 24 Oct 2021 14:35:05 +0800 Subject: [PATCH 19/30] more test cases for dateoffset add/sub --- pandas/tests/tseries/offsets/test_offsets.py | 32 +++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index d7e0320717fba..2e9568b1358f5 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -775,20 +775,30 @@ def test_tick_normalize_raises(tick_classes): @pytest.mark.parametrize( "cases", [ - ("nanoseconds", Timestamp("1970-01-01 00:00:00.000000001")), - ("microseconds", Timestamp("1970-01-01 00:00:00.000001")), - ("seconds", Timestamp("1970-01-01 00:00:01")), - ("minutes", Timestamp("1970-01-01 00:01:00")), - ("hours", Timestamp("1970-01-01 01:00:00")), - ("days", Timestamp("1970-01-02 00:00:00")), - ("weeks", Timestamp("1970-01-08 00:00:00")), - ("months", Timestamp("1970-02-01 00:00:00")), - ("years", Timestamp("1971-01-01 00:00:00")), + ("nanoseconds", 1, Timestamp('1970-01-01 00:00:00.000000001')), + ("nanoseconds", 5, Timestamp('1970-01-01 00:00:00.000000005')), + ("nanoseconds", -1, Timestamp('1969-12-31 23:59:59.999999999')), + ("microseconds", 1, Timestamp('1970-01-01 00:00:00.000001')), + ("microseconds", -1, Timestamp('1969-12-31 23:59:59.999999')), + ("seconds", 1, Timestamp('1970-01-01 00:00:01')), + ("seconds", -1, Timestamp('1969-12-31 23:59:59')), + ("minutes", 1, Timestamp('1970-01-01 00:01:00')), + ("minutes", -1, Timestamp('1969-12-31 23:59:00')), + ("hours", 1, Timestamp('1970-01-01 01:00:00')), + ("hours", -1, Timestamp('1969-12-31 23:00:00')), + ("days", 1, Timestamp('1970-01-02 00:00:00')), + ("days", -1, Timestamp('1969-12-31 00:00:00')), + ("weeks", 1, Timestamp('1970-01-08 00:00:00')), + ("weeks", -1, Timestamp('1969-12-25 00:00:00')), + ("months", 1, Timestamp('1970-02-01 00:00:00')), + ("months", -1, Timestamp('1969-12-01 00:00:00')), + ("years", 1, Timestamp('1971-01-01 00:00:00')), + ("years", -1, Timestamp('1969-01-01 00:00:00')), ], ) def test_dateoffset_add_sub(cases): - time_unit, expected = cases - offset = DateOffset(**{time_unit: 1}) + time_unit, num, expected = cases + offset = DateOffset(**{time_unit: num}) ts = Timestamp(0) + offset assert ts == expected ts -= offset From 8e42c6458732c72de94467a5a2a5d9d9bc1fe444 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 24 Oct 2021 14:44:26 +0800 Subject: [PATCH 20/30] test radd. --- pandas/tests/tseries/offsets/test_offsets.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index 2e9568b1358f5..6ca4c0262ee06 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -797,12 +797,14 @@ def test_tick_normalize_raises(tick_classes): ], ) def test_dateoffset_add_sub(cases): - time_unit, num, expected = cases + time_unit, num, expected = cases offset = DateOffset(**{time_unit: num}) ts = Timestamp(0) + offset assert ts == expected ts -= offset assert ts == Timestamp(0) + ts = offset + Timestamp(0) + assert ts == expected @pytest.mark.parametrize( From 5ca3472a753efdbfa0dbf384aa21ae3df4d3e331 Mon Sep 17 00:00:00 2001 From: tushushu Date: Mon, 25 Oct 2021 14:41:14 +0800 Subject: [PATCH 21/30] code style. --- pandas/tests/tseries/offsets/test_offsets.py | 38 ++++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index 6ca4c0262ee06..fbaf3db79d408 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -775,25 +775,25 @@ def test_tick_normalize_raises(tick_classes): @pytest.mark.parametrize( "cases", [ - ("nanoseconds", 1, Timestamp('1970-01-01 00:00:00.000000001')), - ("nanoseconds", 5, Timestamp('1970-01-01 00:00:00.000000005')), - ("nanoseconds", -1, Timestamp('1969-12-31 23:59:59.999999999')), - ("microseconds", 1, Timestamp('1970-01-01 00:00:00.000001')), - ("microseconds", -1, Timestamp('1969-12-31 23:59:59.999999')), - ("seconds", 1, Timestamp('1970-01-01 00:00:01')), - ("seconds", -1, Timestamp('1969-12-31 23:59:59')), - ("minutes", 1, Timestamp('1970-01-01 00:01:00')), - ("minutes", -1, Timestamp('1969-12-31 23:59:00')), - ("hours", 1, Timestamp('1970-01-01 01:00:00')), - ("hours", -1, Timestamp('1969-12-31 23:00:00')), - ("days", 1, Timestamp('1970-01-02 00:00:00')), - ("days", -1, Timestamp('1969-12-31 00:00:00')), - ("weeks", 1, Timestamp('1970-01-08 00:00:00')), - ("weeks", -1, Timestamp('1969-12-25 00:00:00')), - ("months", 1, Timestamp('1970-02-01 00:00:00')), - ("months", -1, Timestamp('1969-12-01 00:00:00')), - ("years", 1, Timestamp('1971-01-01 00:00:00')), - ("years", -1, Timestamp('1969-01-01 00:00:00')), + ("nanoseconds", 1, Timestamp("1970-01-01 00:00:00.000000001")), + ("nanoseconds", 5, Timestamp("1970-01-01 00:00:00.000000005")), + ("nanoseconds", -1, Timestamp("1969-12-31 23:59:59.999999999")), + ("microseconds", 1, Timestamp("1970-01-01 00:00:00.000001")), + ("microseconds", -1, Timestamp("1969-12-31 23:59:59.999999")), + ("seconds", 1, Timestamp("1970-01-01 00:00:01")), + ("seconds", -1, Timestamp("1969-12-31 23:59:59")), + ("minutes", 1, Timestamp("1970-01-01 00:01:00")), + ("minutes", -1, Timestamp("1969-12-31 23:59:00")), + ("hours", 1, Timestamp("1970-01-01 01:00:00")), + ("hours", -1, Timestamp("1969-12-31 23:00:00")), + ("days", 1, Timestamp("1970-01-02 00:00:00")), + ("days", -1, Timestamp("1969-12-31 00:00:00")), + ("weeks", 1, Timestamp("1970-01-08 00:00:00")), + ("weeks", -1, Timestamp("1969-12-25 00:00:00")), + ("months", 1, Timestamp("1970-02-01 00:00:00")), + ("months", -1, Timestamp("1969-12-01 00:00:00")), + ("years", 1, Timestamp("1971-01-01 00:00:00")), + ("years", -1, Timestamp("1969-01-01 00:00:00")), ], ) def test_dateoffset_add_sub(cases): From 37d19b54a87c1b2e210a52f7607e94b48a06b990 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sat, 30 Oct 2021 21:47:55 +0800 Subject: [PATCH 22/30] remove unused line. --- pandas/_libs/tslibs/timestamps.pyx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index bfb30ac3df530..7dbdc0e3adc7b 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -311,8 +311,7 @@ cdef class _Timestamp(ABCTimestamp): def __sub__(self, other): - if (is_any_td_scalar(other) or is_integer_object(other) or - is_offset_object(other)): + if (is_any_td_scalar(other) or is_integer_object(other)): neg_other = -other return self + neg_other From 9cda54aeff22a55b2917bd1da924459a46eee343 Mon Sep 17 00:00:00 2001 From: tushushu Date: Thu, 2 Dec 2021 22:13:52 +0800 Subject: [PATCH 23/30] what's new --- doc/source/whatsnew/v1.4.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index fd7cb6a69d955..b63bb62a22f8d 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -608,6 +608,7 @@ Datetimelike - Bug in adding a ``np.timedelta64`` object to a :class:`BusinessDay` or :class:`CustomBusinessDay` object incorrectly raising (:issue:`44532`) - Bug in :meth:`Index.insert` for inserting ``np.datetime64``, ``np.timedelta64`` or ``tuple`` into :class:`Index` with ``dtype='object'`` with negative loc adding ``None`` and replacing existing value (:issue:`44509`) - Bug in :meth:`Series.mode` with ``DatetimeTZDtype`` incorrectly returning timezone-naive and ``PeriodDtype`` incorrectly raising (:issue:`41927`) +- Bug in :class:`DateOffset` with ``nanoseconds`` component does not affect :class:`Timestamp` when adding them. (:issue:`43968`) - Timedelta From 0ee9a6fdc092509be3e99599e95af49771cd3ac9 Mon Sep 17 00:00:00 2001 From: tushushu Date: Thu, 2 Dec 2021 22:21:05 +0800 Subject: [PATCH 24/30] remove unnecessary brackets --- pandas/_libs/tslibs/timestamps.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/timestamps.pyx b/pandas/_libs/tslibs/timestamps.pyx index 3c56eeb80fae2..e07d84a26b211 100644 --- a/pandas/_libs/tslibs/timestamps.pyx +++ b/pandas/_libs/tslibs/timestamps.pyx @@ -311,7 +311,7 @@ cdef class _Timestamp(ABCTimestamp): def __sub__(self, other): - if (is_any_td_scalar(other) or is_integer_object(other)): + if is_any_td_scalar(other) or is_integer_object(other): neg_other = -other return self + neg_other From 860a62b9445e91199c4e42162e7ee0272713dfbe Mon Sep 17 00:00:00 2001 From: tushushu Date: Fri, 3 Dec 2021 09:16:34 +0800 Subject: [PATCH 25/30] what's new. --- doc/source/whatsnew/v1.4.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index b63bb62a22f8d..b2d202fd67cea 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -608,7 +608,7 @@ Datetimelike - Bug in adding a ``np.timedelta64`` object to a :class:`BusinessDay` or :class:`CustomBusinessDay` object incorrectly raising (:issue:`44532`) - Bug in :meth:`Index.insert` for inserting ``np.datetime64``, ``np.timedelta64`` or ``tuple`` into :class:`Index` with ``dtype='object'`` with negative loc adding ``None`` and replacing existing value (:issue:`44509`) - Bug in :meth:`Series.mode` with ``DatetimeTZDtype`` incorrectly returning timezone-naive and ``PeriodDtype`` incorrectly raising (:issue:`41927`) -- Bug in :class:`DateOffset` with ``nanoseconds`` component does not affect :class:`Timestamp` when adding them. (:issue:`43968`) +- Bug in :class:`DateOffset`` addition with :class:`Timestamp` where ``offset.nanoseconds`` would not be included in the result. (:issue:`43968`) - Timedelta From 4600a64925a4919a1d5815863a1914f323a2adf7 Mon Sep 17 00:00:00 2001 From: tushushu Date: Fri, 3 Dec 2021 09:25:31 +0800 Subject: [PATCH 26/30] makes the comment more detailed. --- pandas/_libs/tslibs/offsets.pyx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 046db96ac163f..a0afeb8ca37ff 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -186,7 +186,8 @@ def apply_wraps(func): if self.normalize: result = result.normalize() - # nanosecond may be deleted depending on offset process + # If the offset object does not have a nanoseconds component, + # the result's nanosecond component may be lost. if not self.normalize and nano != 0 and not hasattr(self, "nanoseconds"): if result.nanosecond != nano: if result.tz is not None: From 8cf57469fb79abca369648d704d5688f7caef75e Mon Sep 17 00:00:00 2001 From: tushushu Date: Sat, 4 Dec 2021 22:49:52 +0800 Subject: [PATCH 27/30] test case as jbrockmendel demand --- pandas/tests/tseries/offsets/test_offsets.py | 60 ++++++++++---------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index 8d292aee4b2de..99ceb406d2b0d 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -785,38 +785,40 @@ def test_tick_normalize_raises(tick_classes): @pytest.mark.parametrize( - "cases", + "offset_kwargs, ts_arg, expected_arg", [ - ("nanoseconds", 1, Timestamp("1970-01-01 00:00:00.000000001")), - ("nanoseconds", 5, Timestamp("1970-01-01 00:00:00.000000005")), - ("nanoseconds", -1, Timestamp("1969-12-31 23:59:59.999999999")), - ("microseconds", 1, Timestamp("1970-01-01 00:00:00.000001")), - ("microseconds", -1, Timestamp("1969-12-31 23:59:59.999999")), - ("seconds", 1, Timestamp("1970-01-01 00:00:01")), - ("seconds", -1, Timestamp("1969-12-31 23:59:59")), - ("minutes", 1, Timestamp("1970-01-01 00:01:00")), - ("minutes", -1, Timestamp("1969-12-31 23:59:00")), - ("hours", 1, Timestamp("1970-01-01 01:00:00")), - ("hours", -1, Timestamp("1969-12-31 23:00:00")), - ("days", 1, Timestamp("1970-01-02 00:00:00")), - ("days", -1, Timestamp("1969-12-31 00:00:00")), - ("weeks", 1, Timestamp("1970-01-08 00:00:00")), - ("weeks", -1, Timestamp("1969-12-25 00:00:00")), - ("months", 1, Timestamp("1970-02-01 00:00:00")), - ("months", -1, Timestamp("1969-12-01 00:00:00")), - ("years", 1, Timestamp("1971-01-01 00:00:00")), - ("years", -1, Timestamp("1969-01-01 00:00:00")), + ({"nanoseconds": 1}, 0, "1970-01-01 00:00:00.000000001"), + ({"nanoseconds": 5}, 0, "1970-01-01 00:00:00.000000005"), + ({"nanoseconds": -1}, 0, "1969-12-31 23:59:59.999999999"), + ({"microseconds": 1}, 0, "1970-01-01 00:00:00.000001"), + ({"microseconds": -1}, 0, "1969-12-31 23:59:59.999999"), + ({"seconds": 1}, 0, "1970-01-01 00:00:01"), + ({"seconds": -1}, 0, "1969-12-31 23:59:59"), + ({"minutes": 1}, 0, "1970-01-01 00:01:00"), + ({"minutes": -1}, 0, "1969-12-31 23:59:00"), + ({"hours": 1}, 0, "1970-01-01 01:00:00"), + ({"hours": -1}, 0, "1969-12-31 23:00:00"), + ({"days": 1}, 0, "1970-01-02 00:00:00"), + ({"days": -1}, 0, "1969-12-31 00:00:00"), + ({"weeks": 1}, 0, "1970-01-08 00:00:00"), + ({"weeks": -1}, 0, "1969-12-25 00:00:00"), + ({"months": 1}, 0, "1970-02-01 00:00:00"), + ({"months": -1}, 0, "1969-12-01 00:00:00"), + ({"years": 1}, 0, "1971-01-01 00:00:00"), + ({"years": -1}, 0, "1969-01-01 00:00:00"), + ({"minutes": 2, "nanoseconds": 9}, 4, "1970-01-01 00:02:00.000000013"), ], ) -def test_dateoffset_add_sub(cases): - time_unit, num, expected = cases - offset = DateOffset(**{time_unit: num}) - ts = Timestamp(0) + offset - assert ts == expected - ts -= offset - assert ts == Timestamp(0) - ts = offset + Timestamp(0) - assert ts == expected +def test_dateoffset_add_sub(offset_kwargs, ts_arg, expected_arg): + offset = DateOffset(**offset_kwargs) + ts = Timestamp(ts_arg) + result = ts + offset + expected = Timestamp(expected_arg) + assert result == expected + result -= offset + assert result == ts + result = offset + ts + assert result == expected @pytest.mark.parametrize( From a210baf3a62519c6e2025800e824b07c4810bc85 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 5 Dec 2021 12:02:16 +0800 Subject: [PATCH 28/30] trigger the CI without a commit From 24fe768e95f54bbdf3e59b33bd9a0f0a9b02f949 Mon Sep 17 00:00:00 2001 From: tushushu Date: Wed, 8 Dec 2021 01:51:00 +0800 Subject: [PATCH 29/30] split dateoffset test func --- pandas/tests/tseries/offsets/test_offsets.py | 57 ++++++++++++-------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index 99ceb406d2b0d..f80619b1f9198 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -785,33 +785,32 @@ def test_tick_normalize_raises(tick_classes): @pytest.mark.parametrize( - "offset_kwargs, ts_arg, expected_arg", + "offset_kwargs, expected_arg", [ - ({"nanoseconds": 1}, 0, "1970-01-01 00:00:00.000000001"), - ({"nanoseconds": 5}, 0, "1970-01-01 00:00:00.000000005"), - ({"nanoseconds": -1}, 0, "1969-12-31 23:59:59.999999999"), - ({"microseconds": 1}, 0, "1970-01-01 00:00:00.000001"), - ({"microseconds": -1}, 0, "1969-12-31 23:59:59.999999"), - ({"seconds": 1}, 0, "1970-01-01 00:00:01"), - ({"seconds": -1}, 0, "1969-12-31 23:59:59"), - ({"minutes": 1}, 0, "1970-01-01 00:01:00"), - ({"minutes": -1}, 0, "1969-12-31 23:59:00"), - ({"hours": 1}, 0, "1970-01-01 01:00:00"), - ({"hours": -1}, 0, "1969-12-31 23:00:00"), - ({"days": 1}, 0, "1970-01-02 00:00:00"), - ({"days": -1}, 0, "1969-12-31 00:00:00"), - ({"weeks": 1}, 0, "1970-01-08 00:00:00"), - ({"weeks": -1}, 0, "1969-12-25 00:00:00"), - ({"months": 1}, 0, "1970-02-01 00:00:00"), - ({"months": -1}, 0, "1969-12-01 00:00:00"), - ({"years": 1}, 0, "1971-01-01 00:00:00"), - ({"years": -1}, 0, "1969-01-01 00:00:00"), - ({"minutes": 2, "nanoseconds": 9}, 4, "1970-01-01 00:02:00.000000013"), + ({"nanoseconds": 1}, "1970-01-01 00:00:00.000000001"), + ({"nanoseconds": 5}, "1970-01-01 00:00:00.000000005"), + ({"nanoseconds": -1}, "1969-12-31 23:59:59.999999999"), + ({"microseconds": 1}, "1970-01-01 00:00:00.000001"), + ({"microseconds": -1}, "1969-12-31 23:59:59.999999"), + ({"seconds": 1}, "1970-01-01 00:00:01"), + ({"seconds": -1}, "1969-12-31 23:59:59"), + ({"minutes": 1}, "1970-01-01 00:01:00"), + ({"minutes": -1}, "1969-12-31 23:59:00"), + ({"hours": 1}, "1970-01-01 01:00:00"), + ({"hours": -1}, "1969-12-31 23:00:00"), + ({"days": 1}, "1970-01-02 00:00:00"), + ({"days": -1}, "1969-12-31 00:00:00"), + ({"weeks": 1}, "1970-01-08 00:00:00"), + ({"weeks": -1}, "1969-12-25 00:00:00"), + ({"months": 1}, "1970-02-01 00:00:00"), + ({"months": -1}, "1969-12-01 00:00:00"), + ({"years": 1}, "1971-01-01 00:00:00"), + ({"years": -1}, "1969-01-01 00:00:00"), ], ) -def test_dateoffset_add_sub(offset_kwargs, ts_arg, expected_arg): +def test_dateoffset_add_sub(offset_kwargs, expected_arg): offset = DateOffset(**offset_kwargs) - ts = Timestamp(ts_arg) + ts = Timestamp(0) result = ts + offset expected = Timestamp(expected_arg) assert result == expected @@ -821,6 +820,18 @@ def test_dateoffset_add_sub(offset_kwargs, ts_arg, expected_arg): assert result == expected +def test_dataoffset_add_sub_timestamp_with_nano() + offset = DateOffset(minutes=2, nanoseconds=9) + ts = Timestamp(4) + result = ts + offset + expected = Timestamp("1970-01-01 00:02:00.000000013") + assert result == expected + result -= offset + assert result == ts + result = offset + ts + assert result == expected + + @pytest.mark.parametrize( "attribute", [ From 3f49876f452a6fd004a8ae2906dfafcdcccbc600 Mon Sep 17 00:00:00 2001 From: tushushu Date: Wed, 8 Dec 2021 20:32:24 +0800 Subject: [PATCH 30/30] fix typo --- pandas/tests/tseries/offsets/test_offsets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index f80619b1f9198..fbece04c23e0f 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -820,7 +820,7 @@ def test_dateoffset_add_sub(offset_kwargs, expected_arg): assert result == expected -def test_dataoffset_add_sub_timestamp_with_nano() +def test_dataoffset_add_sub_timestamp_with_nano(): offset = DateOffset(minutes=2, nanoseconds=9) ts = Timestamp(4) result = ts + offset