Skip to content

Commit b211e9e

Browse files
committed
fix: raise error when converting NaT to int
Previously, it was converting it to -2^63.
1 parent e4ca405 commit b211e9e

File tree

4 files changed

+42
-4
lines changed

4 files changed

+42
-4
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,7 @@ Datetimelike
964964
- Bug in :meth:`to_datetime` reports incorrect index in case of any failure scenario. (:issue:`58298`)
965965
- Bug in :meth:`to_datetime` with ``format="ISO8601"`` and ``utc=True`` where naive timestamps incorrectly inherited timezone offset from previous timestamps in a series. (:issue:`61389`)
966966
- Bug in :meth:`to_datetime` wrongly converts when ``arg`` is a ``np.datetime64`` object with unit of ``ps``. (:issue:`60341`)
967+
- Bug in Datetime-like arrays converting ``NaT`` to -(2**63) when casting to integer. Now it raises ``IntCastingNaNError`` (:issue:`59711`)
967968
- Bug in comparison between objects with ``np.datetime64`` dtype and ``timestamp[pyarrow]`` dtypes incorrectly raising ``TypeError`` (:issue:`60937`)
968969
- Bug in comparison between objects with pyarrow date dtype and ``timestamp[pyarrow]`` or ``np.datetime64`` dtype failing to consider these as non-comparable (:issue:`62157`)
969970
- Bug in constructing arrays with :class:`ArrowDtype` with ``timestamp`` type incorrectly allowing ``Decimal("NaN")`` (:issue:`61773`)

pandas/core/arrays/datetimelike.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
)
8888
from pandas.util._exceptions import find_stack_level
8989

90+
from pandas.core.dtypes.astype import check_to_int_nansafe
9091
from pandas.core.dtypes.cast import construct_1d_object_array_from_listlike
9192
from pandas.core.dtypes.common import (
9293
is_all_strings,
@@ -490,6 +491,7 @@ def astype(self, dtype, copy: bool = True):
490491
elif dtype.kind in "iu":
491492
# we deliberately ignore int32 vs. int64 here.
492493
# See https://github.com/pandas-dev/pandas/issues/24381 for more.
494+
check_to_int_nansafe(self, infinite_check=False)
493495
values = self.asi8
494496
if dtype != np.int64:
495497
raise TypeError(

pandas/core/dtypes/astype.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
ExtensionDtype,
2828
NumpyEADtype,
2929
)
30+
from pandas.core.dtypes.missing import isna
3031

3132
if TYPE_CHECKING:
3233
from pandas._typing import (
@@ -138,10 +139,7 @@ def _astype_float_to_int_nansafe(
138139
"""
139140
astype with a check preventing converting NaN to an meaningless integer value.
140141
"""
141-
if not np.isfinite(values).all():
142-
raise IntCastingNaNError(
143-
"Cannot convert non-finite values (NA or inf) to integer"
144-
)
142+
check_to_int_nansafe(values)
145143
if dtype.kind == "u":
146144
# GH#45151
147145
if not (values >= 0).all():
@@ -151,6 +149,34 @@ def _astype_float_to_int_nansafe(
151149
return values.astype(dtype, copy=copy)
152150

153151

152+
def check_to_int_nansafe(values: np.ndarray, infinite_check: bool = True):
153+
"""
154+
Validate that values can be safely converted to integer type.
155+
156+
Parameters
157+
----------
158+
values : np.ndarray
159+
Array of values to check for conversion to integer.
160+
infinite_check : bool
161+
If True, check for both infinite and missing values.
162+
If False, check only for missing values.
163+
This distinction exists
164+
because ``np.isfinite`` isn't compatible with ``np.ufunc``.
165+
166+
Raises
167+
------
168+
IntCastingNaNError
169+
If any non-finite value is detected.
170+
"""
171+
error_msg = "Cannot convert non-finite values (NA or inf) to integer"
172+
if infinite_check:
173+
if not np.isfinite(values).all():
174+
raise IntCastingNaNError(error_msg)
175+
else:
176+
if isna(values).any():
177+
raise IntCastingNaNError(error_msg)
178+
179+
154180
def astype_array(values: ArrayLike, dtype: DtypeObj, copy: bool = False) -> ArrayLike:
155181
"""
156182
Cast array (ndarray or ExtensionArray) to the new dtype.

pandas/tests/series/methods/test_astype.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,15 @@ def test_astype_cast_nan_inf_int(self, any_int_numpy_dtype, value):
389389
with pytest.raises(ValueError, match=msg):
390390
ser.astype(any_int_numpy_dtype)
391391

392+
@pytest.mark.parametrize("dtype", tm.DATETIME64_DTYPES + tm.TIMEDELTA64_DTYPES)
393+
def test_int_cast_raises_with_datetime(self, dtype):
394+
# GH 59711
395+
ser = Series([np.nan], dtype=dtype)
396+
397+
msg = r"Cannot convert non-finite values \(NA or inf\) to integer"
398+
with pytest.raises(ValueError, match=msg):
399+
ser.astype(int)
400+
392401
def test_astype_cast_object_int_fail(self, any_int_numpy_dtype):
393402
arr = Series(["car", "house", "tree", "1"])
394403
msg = r"invalid literal for int\(\) with base 10: 'car'"

0 commit comments

Comments
 (0)