Skip to content

Commit b6a058b

Browse files
authored
BUG: Period + np.timedelta64(nat) (#47196)
* BUG: Period + np.timedelta64(nat) * GH ref * test reversed subtraction raises * parametrize over unit
1 parent 4791cd7 commit b6a058b

File tree

3 files changed

+31
-11
lines changed

3 files changed

+31
-11
lines changed

doc/source/whatsnew/v1.5.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,7 @@ Period
828828
- Bug in :meth:`Period.strftime` and :meth:`PeriodIndex.strftime`, directives ``%l`` and ``%u`` were giving wrong results (:issue:`46252`)
829829
- Bug in inferring an incorrect ``freq`` when passing a string to :class:`Period` microseconds that are a multiple of 1000 (:issue:`46811`)
830830
- Bug in constructing a :class:`Period` from a :class:`Timestamp` or ``np.datetime64`` object with non-zero nanoseconds and ``freq="ns"`` incorrectly truncating the nanoseconds (:issue:`46811`)
831+
- Bug in adding ``np.timedelta64("NaT", "ns")`` to a :class:`Period` with a timedelta-like freq incorrectly raising ``IncompatibleFrequency`` instead of returning ``NaT`` (:issue:`47196`)
831832
-
832833

833834
Plotting

pandas/_libs/tslibs/period.pyx

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ from pandas._libs.tslibs.np_datetime cimport (
5050
check_dts_bounds,
5151
dt64_to_dtstruct,
5252
dtstruct_to_dt64,
53+
get_timedelta64_value,
5354
npy_datetimestruct,
5455
npy_datetimestruct_to_datetime,
5556
pandas_datetime_to_datetimestruct,
@@ -1682,17 +1683,22 @@ cdef class _Period(PeriodMixin):
16821683
cdef:
16831684
int64_t inc
16841685

1685-
if is_tick_object(self.freq):
1686-
try:
1687-
inc = delta_to_nanoseconds(other, reso=self.freq._reso, round_ok=False)
1688-
except ValueError as err:
1689-
raise IncompatibleFrequency("Input cannot be converted to "
1690-
f"Period(freq={self.freqstr})") from err
1691-
# TODO: overflow-check here
1692-
ordinal = self.ordinal + inc
1693-
return Period(ordinal=ordinal, freq=self.freq)
1694-
raise IncompatibleFrequency("Input cannot be converted to "
1695-
f"Period(freq={self.freqstr})")
1686+
if not is_tick_object(self.freq):
1687+
raise IncompatibleFrequency("Input cannot be converted to "
1688+
f"Period(freq={self.freqstr})")
1689+
1690+
if util.is_timedelta64_object(other) and get_timedelta64_value(other) == NPY_NAT:
1691+
# i.e. np.timedelta64("nat")
1692+
return NaT
1693+
1694+
try:
1695+
inc = delta_to_nanoseconds(other, reso=self.freq._reso, round_ok=False)
1696+
except ValueError as err:
1697+
raise IncompatibleFrequency("Input cannot be converted to "
1698+
f"Period(freq={self.freqstr})") from err
1699+
# TODO: overflow-check here
1700+
ordinal = self.ordinal + inc
1701+
return Period(ordinal=ordinal, freq=self.freq)
16961702

16971703
def _add_offset(self, other) -> "Period":
16981704
# Non-Tick DateOffset other

pandas/tests/scalar/period/test_period.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,19 @@ def test_comparison_numpy_zerodim_arr(self, zerodim_arr, expected):
11871187

11881188

11891189
class TestArithmetic:
1190+
@pytest.mark.parametrize("unit", ["ns", "us", "ms", "s", "m"])
1191+
def test_add_sub_td64_nat(self, unit):
1192+
# GH#47196
1193+
per = Period("2022-06-01", "D")
1194+
nat = np.timedelta64("NaT", unit)
1195+
1196+
assert per + nat is NaT
1197+
assert nat + per is NaT
1198+
assert per - nat is NaT
1199+
1200+
with pytest.raises(TypeError, match="unsupported operand"):
1201+
nat - per
1202+
11901203
def test_sub_delta(self):
11911204
left, right = Period("2011", freq="A"), Period("2007", freq="A")
11921205
result = left - right

0 commit comments

Comments
 (0)