Skip to content

Commit 17b55aa

Browse files
authored
REF: disallow ints from delta_to_nanoseconds (#46378)
1 parent bd1263f commit 17b55aa

File tree

5 files changed

+25
-22
lines changed

5 files changed

+25
-22
lines changed

pandas/_libs/tslibs/timedeltas.pyx

+3-3
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,11 @@ cpdef int64_t delta_to_nanoseconds(delta) except? -1:
174174
if is_tick_object(delta):
175175
return delta.nanos
176176
if isinstance(delta, _Timedelta):
177-
delta = delta.value
177+
return delta.value
178+
178179
if is_timedelta64_object(delta):
179180
return get_timedelta64_value(ensure_td64ns(delta))
180-
if is_integer_object(delta):
181-
return delta
181+
182182
if PyDelta_Check(delta):
183183
try:
184184
return (

pandas/core/arrays/datetimelike.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -1316,7 +1316,9 @@ def __add__(self, other):
13161316
elif is_integer_dtype(other_dtype):
13171317
if not is_period_dtype(self.dtype):
13181318
raise integer_op_not_supported(self)
1319-
result = cast("PeriodArray", self)._addsub_int_array(other, operator.add)
1319+
result = cast("PeriodArray", self)._addsub_int_array_or_scalar(
1320+
other, operator.add
1321+
)
13201322
else:
13211323
# Includes Categorical, other ExtensionArrays
13221324
# For PeriodDtype, if self is a TimedeltaArray and other is a
@@ -1376,7 +1378,9 @@ def __sub__(self, other):
13761378
elif is_integer_dtype(other_dtype):
13771379
if not is_period_dtype(self.dtype):
13781380
raise integer_op_not_supported(self)
1379-
result = cast("PeriodArray", self)._addsub_int_array(other, operator.sub)
1381+
result = cast("PeriodArray", self)._addsub_int_array_or_scalar(
1382+
other, operator.sub
1383+
)
13801384
else:
13811385
# Includes ExtensionArrays, float_dtype
13821386
return NotImplemented

pandas/core/arrays/period.py

+6-13
Original file line numberDiff line numberDiff line change
@@ -747,16 +747,16 @@ def _sub_period_array(self, other):
747747
new_values[mask] = NaT
748748
return new_values
749749

750-
def _addsub_int_array(
751-
self, other: np.ndarray, op: Callable[[Any, Any], Any]
750+
def _addsub_int_array_or_scalar(
751+
self, other: np.ndarray | int, op: Callable[[Any, Any], Any]
752752
) -> PeriodArray:
753753
"""
754754
Add or subtract array of integers; equivalent to applying
755755
`_time_shift` pointwise.
756756
757757
Parameters
758758
----------
759-
other : np.ndarray[integer-dtype]
759+
other : np.ndarray[int64] or int
760760
op : {operator.add, operator.sub}
761761
762762
Returns
@@ -775,12 +775,7 @@ def _add_offset(self, other: BaseOffset):
775775
assert not isinstance(other, Tick)
776776

777777
self._require_matching_freq(other, base=True)
778-
779-
# Note: when calling parent class's _add_timedeltalike_scalar,
780-
# it will call delta_to_nanoseconds(delta). Because delta here
781-
# is an integer, delta_to_nanoseconds will return it unchanged.
782-
result = super()._add_timedeltalike_scalar(other.n)
783-
return type(self)(result, freq=self.freq)
778+
return self._addsub_int_array_or_scalar(other.n, operator.add)
784779

785780
def _add_timedeltalike_scalar(self, other):
786781
"""
@@ -800,10 +795,8 @@ def _add_timedeltalike_scalar(self, other):
800795
# special handling for np.timedelta64("NaT"), avoid calling
801796
# _check_timedeltalike_freq_compat as that would raise TypeError
802797
other = self._check_timedeltalike_freq_compat(other)
798+
other = np.timedelta64(other, "ns")
803799

804-
# Note: when calling parent class's _add_timedeltalike_scalar,
805-
# it will call delta_to_nanoseconds(delta). Because delta here
806-
# is an integer, delta_to_nanoseconds will return it unchanged.
807800
return super()._add_timedeltalike_scalar(other)
808801

809802
def _add_timedelta_arraylike(self, other):
@@ -828,7 +821,7 @@ def _add_timedelta_arraylike(self, other):
828821
# all-NaT TimedeltaIndex is equivalent to a single scalar td64 NaT
829822
return self + np.timedelta64("NaT")
830823

831-
ordinals = self._addsub_int_array(delta, operator.add).asi8
824+
ordinals = self._addsub_int_array_or_scalar(delta, operator.add).asi8
832825
return type(self)(ordinals, dtype=self.dtype)
833826

834827
def _check_timedeltalike_freq_compat(self, other):

pandas/core/indexes/period.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ def __new__(
272272
def values(self) -> np.ndarray:
273273
return np.asarray(self, dtype=object)
274274

275-
def _maybe_convert_timedelta(self, other):
275+
def _maybe_convert_timedelta(self, other) -> int | npt.NDArray[np.int64]:
276276
"""
277277
Convert timedelta-like input to an integer multiple of self.freq
278278

pandas/tests/tslibs/test_timedeltas.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@
3030
24 * 3600e9 + 111,
3131
), # GH43764
3232
(offsets.Nano(125), 125),
33-
(1, 1),
34-
(np.int64(2), 2),
35-
(np.int32(3), 3),
3633
],
3734
)
3835
def test_delta_to_nanoseconds(obj, expected):
@@ -46,6 +43,15 @@ def test_delta_to_nanoseconds_error():
4643
with pytest.raises(TypeError, match="<class 'numpy.ndarray'>"):
4744
delta_to_nanoseconds(obj)
4845

46+
with pytest.raises(TypeError, match="float"):
47+
delta_to_nanoseconds(1.5)
48+
with pytest.raises(TypeError, match="int"):
49+
delta_to_nanoseconds(1)
50+
with pytest.raises(TypeError, match="int"):
51+
delta_to_nanoseconds(np.int64(2))
52+
with pytest.raises(TypeError, match="int"):
53+
delta_to_nanoseconds(np.int32(3))
54+
4955

5056
def test_huge_nanoseconds_overflow():
5157
# GH 32402

0 commit comments

Comments
 (0)