From 58aebf1940b56b77279174f5413b76a5aaba465c Mon Sep 17 00:00:00 2001 From: MeeseeksMachine <39504233+meeseeksmachine@users.noreply.github.com> Date: Thu, 10 Feb 2022 16:19:15 -0800 Subject: [PATCH] Backport PR #45909: BUG: DateOffset(n) not defaulting to days (#45918) Co-authored-by: Matthew Roeschke --- doc/source/whatsnew/v1.4.1.rst | 2 +- pandas/_libs/tslibs/offsets.pyx | 7 ++++++- pandas/tests/tseries/offsets/test_offsets.py | 10 ++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.4.1.rst b/doc/source/whatsnew/v1.4.1.rst index 1acfbe0794b26..19d8a2a9302d7 100644 --- a/doc/source/whatsnew/v1.4.1.rst +++ b/doc/source/whatsnew/v1.4.1.rst @@ -24,7 +24,7 @@ Fixed regressions - Regression in :meth:`~Index.join` with overlapping :class:`IntervalIndex` raising an ``InvalidIndexError`` (:issue:`45661`) - Regression when setting values with :meth:`Series.loc` raising with all ``False`` indexer and :class:`Series` on the right hand side (:issue:`45778`) - Regression in :func:`read_sql` with a DBAPI2 connection that is not an instance of ``sqlite3.Connection`` incorrectly requiring SQLAlchemy be installed (:issue:`45660`) -- +- Regression in :class:`DateOffset` when constructing with an integer argument with no keywords (e.g. ``pd.DateOffset(n)``) would behave like ``datetime.timedelta(days=0)`` (:issue:`45643`, :issue:`45890`) .. --------------------------------------------------------------------------- diff --git a/pandas/_libs/tslibs/offsets.pyx b/pandas/_libs/tslibs/offsets.pyx index 6df4abc160b0b..dc049e9195d3f 100644 --- a/pandas/_libs/tslibs/offsets.pyx +++ b/pandas/_libs/tslibs/offsets.pyx @@ -333,8 +333,12 @@ cdef _determine_offset(kwds): else: # sub-daily offset - use timedelta (tz-aware) offset = timedelta(**kwds_no_nanos) + elif any(nano in kwds for nano in ('nanosecond', 'nanoseconds')): + offset = timedelta(days=0) else: - offset = timedelta(0) + # GH 45643/45890: (historically) defaults to 1 day for non-nano + # since datetime.timedelta doesn't handle nanoseconds + offset = timedelta(days=1) return offset, use_relativedelta @@ -1223,6 +1227,7 @@ class DateOffset(RelativeDeltaOffset, metaclass=OffsetMeta): ---------- n : int, default 1 The number of time periods the offset represents. + If specified without a temporal pattern, defaults to n days. normalize : bool, default False Whether to round the result of a DateOffset addition down to the previous midnight. diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index 5dcfd0019e93f..0737029e098c5 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -854,3 +854,13 @@ def test_dateoffset_misc(): oset.freqstr assert not offsets.DateOffset(months=2) == 2 + + +@pytest.mark.parametrize("n", [-1, 1, 3]) +def test_construct_int_arg_no_kwargs_assumed_days(n): + # GH 45890, 45643 + offset = DateOffset(n) + assert offset._offset == timedelta(1) + result = Timestamp(2022, 1, 2) + offset + expected = Timestamp(2022, 1, 2 + n) + assert result == expected