Skip to content

Commit 6482f10

Browse files
srotondoKingOfTheShow69mroeschke
authored andcommitted
BUG: Fixed ignoring of nanoseconds when adding to series pandas-dev#47856 (pandas-dev#48008)
* BUG: Fixed ignoring of nanoseconds when adding to series pandas-dev#47856 * Update doc/source/whatsnew/v1.5.0.rst Co-authored-by: Matthew Roeschke <[email protected]> * BUG: Renamed test variables pandas-dev#47856 * BUG: Changed added if-else for performance pandas-dev#47856 * Update pandas/_libs/tslibs/offsets.pyx Co-authored-by: Matthew Roeschke <[email protected]> * BUG: Used getattr for nano check pandas-dev#47856 Co-authored-by: Steven Rotondo <[email protected]> Co-authored-by: Matthew Roeschke <[email protected]>
1 parent 4caa8bc commit 6482f10

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

doc/source/whatsnew/v1.5.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,7 @@ Datetimelike
896896
- Bug in :meth:`DatetimeIndex.resolution` incorrectly returning "day" instead of "nanosecond" for nanosecond-resolution indexes (:issue:`46903`)
897897
- Bug in :class:`Timestamp` with an integer or float value and ``unit="Y"`` or ``unit="M"`` giving slightly-wrong results (:issue:`47266`)
898898
- Bug in :class:`.DatetimeArray` construction when passed another :class:`.DatetimeArray` and ``freq=None`` incorrectly inferring the freq from the given array (:issue:`47296`)
899+
- Bug when adding a :class:`DateOffset` to a :class:`Series` would not add the ``nanoseconds`` field (:issue:`47856`)
899900
-
900901

901902
Timedelta

pandas/_libs/tslibs/offsets.pyx

+8-3
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,8 @@ _relativedelta_kwds = {"years", "months", "weeks", "days", "year", "month",
297297

298298
cdef _determine_offset(kwds):
299299
# timedelta is used for sub-daily plural offsets and all singular
300-
# offsets relativedelta is used for plural offsets of daily length or
301-
# more nanosecond(s) are handled by apply_wraps
300+
# offsets, relativedelta is used for plural offsets of daily length or
301+
# more, nanosecond(s) are handled by apply_wraps
302302
kwds_no_nanos = dict(
303303
(k, v) for k, v in kwds.items()
304304
if k not in ('nanosecond', 'nanoseconds')
@@ -1163,7 +1163,12 @@ cdef class RelativeDeltaOffset(BaseOffset):
11631163
return dt64other
11641164
elif not self._use_relativedelta and hasattr(self, "_offset"):
11651165
# timedelta
1166-
delta = Timedelta(self._offset * self.n)
1166+
num_nano = getattr(self, "nanoseconds", 0)
1167+
if num_nano != 0:
1168+
rem_nano = Timedelta(nanoseconds=num_nano)
1169+
delta = Timedelta((self._offset + rem_nano) * self.n)
1170+
else:
1171+
delta = Timedelta(self._offset * self.n)
11671172
td = (<_Timedelta>delta)._as_reso(reso)
11681173
return dt64other + td
11691174
else:

pandas/tests/tseries/offsets/test_offsets.py

+25-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
from pandas import (
3535
DatetimeIndex,
36+
Series,
3637
date_range,
3738
)
3839
import pandas._testing as tm
@@ -987,7 +988,7 @@ def test_dateoffset_add_sub(offset_kwargs, expected_arg):
987988
assert result == expected
988989

989990

990-
def test_dataoffset_add_sub_timestamp_with_nano():
991+
def test_dateoffset_add_sub_timestamp_with_nano():
991992
offset = DateOffset(minutes=2, nanoseconds=9)
992993
ts = Timestamp(4)
993994
result = ts + offset
@@ -1032,3 +1033,26 @@ def test_construct_int_arg_no_kwargs_assumed_days(n):
10321033
result = Timestamp(2022, 1, 2) + offset
10331034
expected = Timestamp(2022, 1, 2 + n)
10341035
assert result == expected
1036+
1037+
1038+
@pytest.mark.parametrize(
1039+
"offset, expected",
1040+
[
1041+
(
1042+
DateOffset(minutes=7, nanoseconds=18),
1043+
Timestamp("2022-01-01 00:07:00.000000018"),
1044+
),
1045+
(DateOffset(nanoseconds=3), Timestamp("2022-01-01 00:00:00.000000003")),
1046+
],
1047+
)
1048+
def test_dateoffset_add_sub_timestamp_series_with_nano(offset, expected):
1049+
# GH 47856
1050+
start_time = Timestamp("2022-01-01")
1051+
teststamp = start_time
1052+
testseries = Series([start_time])
1053+
testseries = testseries + offset
1054+
assert testseries[0] == expected
1055+
testseries -= offset
1056+
assert testseries[0] == teststamp
1057+
testseries = offset + testseries
1058+
assert testseries[0] == expected

0 commit comments

Comments
 (0)