Skip to content

Commit 122d502

Browse files
authored
BUG: .item() incorrectly casts td64/dt64 to int (#38512)
1 parent 53d1622 commit 122d502

File tree

4 files changed

+39
-3
lines changed

4 files changed

+39
-3
lines changed

pandas/core/dtypes/cast.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ def infer_dtype_from_scalar(val, pandas_dtype: bool = False) -> Tuple[DtypeObj,
699699
raise ValueError(msg)
700700

701701
dtype = val.dtype
702-
val = val.item()
702+
val = lib.item_from_zerodim(val)
703703

704704
elif isinstance(val, str):
705705

pandas/core/tools/timedeltas.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import numpy as np
66

7+
from pandas._libs import lib
78
from pandas._libs.tslibs import NaT
89
from pandas._libs.tslibs.timedeltas import Timedelta, parse_timedelta_unit
910

@@ -117,7 +118,7 @@ def to_timedelta(arg, unit=None, errors="raise"):
117118
return _convert_listlike(arg, unit=unit, errors=errors, name=arg.name)
118119
elif isinstance(arg, np.ndarray) and arg.ndim == 0:
119120
# extract array scalar and process below
120-
arg = arg.item()
121+
arg = lib.item_from_zerodim(arg)
121122
elif is_list_like(arg) and getattr(arg, "ndim", 1) == 1:
122123
return _convert_listlike(arg, unit=unit, errors=errors)
123124
elif getattr(arg, "ndim", 1) > 1:

pandas/tests/dtypes/cast/test_infer_dtype.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
import numpy as np
44
import pytest
55

6-
from pandas.core.dtypes.cast import infer_dtype_from_array, infer_dtype_from_scalar
6+
from pandas.core.dtypes.cast import (
7+
infer_dtype_from,
8+
infer_dtype_from_array,
9+
infer_dtype_from_scalar,
10+
)
711
from pandas.core.dtypes.common import is_dtype_equal
812

913
from pandas import (
@@ -171,3 +175,17 @@ def test_infer_dtype_from_scalar_errors():
171175
def test_infer_dtype_from_array(arr, expected, pandas_dtype):
172176
dtype, _ = infer_dtype_from_array(arr, pandas_dtype=pandas_dtype)
173177
assert is_dtype_equal(dtype, expected)
178+
179+
180+
@pytest.mark.parametrize("cls", [np.datetime64, np.timedelta64])
181+
def test_infer_dtype_from_scalar_zerodim_datetimelike(cls):
182+
# ndarray.item() can incorrectly return int instead of td64/dt64
183+
val = cls(1234, "ns")
184+
arr = np.array(val)
185+
186+
dtype, res = infer_dtype_from_scalar(arr)
187+
assert dtype.type is cls
188+
assert isinstance(res, cls)
189+
190+
dtype, res = infer_dtype_from(arr)
191+
assert dtype.type is cls

pandas/tests/tools/test_to_timedelta.py

+17
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,20 @@ def test_to_timedelta_precision_over_nanos(self, input, expected, func):
227227
expected = pd.Timedelta(expected)
228228
result = func(input)
229229
assert result == expected
230+
231+
def test_to_timedelta_zerodim(self):
232+
# ndarray.item() incorrectly returns int for dt64[ns] and td64[ns]
233+
dt64 = pd.Timestamp.now().to_datetime64()
234+
arg = np.array(dt64)
235+
236+
msg = (
237+
"Value must be Timedelta, string, integer, float, timedelta "
238+
"or convertible, not datetime64"
239+
)
240+
with pytest.raises(ValueError, match=msg):
241+
to_timedelta(arg)
242+
243+
arg2 = arg.view("m8[ns]")
244+
result = to_timedelta(arg2)
245+
assert isinstance(result, pd.Timedelta)
246+
assert result.value == dt64.view("i8")

0 commit comments

Comments
 (0)