Skip to content

Commit 7c669c2

Browse files
authored
REF: catch less in maybe_cast_to_datetime (#40037)
1 parent 8bdd081 commit 7c669c2

File tree

6 files changed

+26
-10
lines changed

6 files changed

+26
-10
lines changed

pandas/_libs/tslibs/timedeltas.pyx

+5-1
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,13 @@ def array_to_timedelta64(ndarray[object] values, str unit=None, str errors="rais
347347
for i in range(n):
348348
try:
349349
result[i] = convert_to_timedelta64(values[i], parsed_unit)
350-
except ValueError:
350+
except ValueError as err:
351351
if errors == 'coerce':
352352
result[i] = NPY_NAT
353+
elif "unit abbreviation w/o a number" in str(err):
354+
# re-raise with more pertinent message
355+
msg = f"Could not convert '{values[i]}' to NumPy timedelta"
356+
raise ValueError(msg) from err
353357
else:
354358
raise
355359

pandas/core/dtypes/cast.py

+14-6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
)
2727
import warnings
2828

29+
from dateutil.parser import ParserError
2930
import numpy as np
3031

3132
from pandas._libs import (
@@ -1315,11 +1316,7 @@ def convert_dtypes(
13151316
if (
13161317
convert_string or convert_integer or convert_boolean or convert_floating
13171318
) and not is_extension:
1318-
try:
1319-
inferred_dtype = lib.infer_dtype(input_array)
1320-
except ValueError:
1321-
# Required to catch due to Period. Can remove once GH 23553 is fixed
1322-
inferred_dtype = input_array.dtype
1319+
inferred_dtype = lib.infer_dtype(input_array)
13231320

13241321
if not convert_string and is_string_dtype(inferred_dtype):
13251322
inferred_dtype = input_array.dtype
@@ -1591,8 +1588,19 @@ def maybe_cast_to_datetime(
15911588
value = to_timedelta(value, errors="raise")._values
15921589
except OutOfBoundsDatetime:
15931590
raise
1594-
except (ValueError, TypeError):
1591+
except ParserError:
1592+
# Note: ParserError subclasses ValueError
1593+
# str that we can't parse to datetime
15951594
pass
1595+
except ValueError as err:
1596+
if "mixed datetimes and integers in passed array" in str(err):
1597+
# array_to_datetime does not allow this;
1598+
# when called from _try_cast, this will be followed
1599+
# by a call to construct_1d_ndarray_preserving_na
1600+
# which will convert these
1601+
pass
1602+
else:
1603+
raise
15961604

15971605
# coerce datetimelike to object
15981606
elif is_datetime64_dtype(

pandas/tests/frame/test_constructors.py

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ def test_array_of_dt64_nat_with_td64dtype_raises(self, frame_or_series):
8585
arr = arr.reshape(1, 1)
8686

8787
msg = "Could not convert object to NumPy timedelta"
88+
if frame_or_series is Series:
89+
msg = "Invalid type for timedelta scalar: <class 'numpy.datetime64'>"
8890
with pytest.raises(ValueError, match=msg):
8991
frame_or_series(arr, dtype="m8[ns]")
9092

pandas/tests/indexes/datetimes/test_indexing.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,8 @@ def test_get_indexer(self):
617617
pd.Timedelta("1 hour").to_timedelta64(),
618618
"foo",
619619
]
620-
with pytest.raises(ValueError, match="abbreviation w/o a number"):
620+
msg = "Could not convert 'foo' to NumPy timedelta"
621+
with pytest.raises(ValueError, match=msg):
621622
idx.get_indexer(target, "nearest", tolerance=tol_bad)
622623
with pytest.raises(ValueError, match="abbreviation w/o a number"):
623624
idx.get_indexer(idx[[0]], method="nearest", tolerance="foo")

pandas/tests/series/test_constructors.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1332,7 +1332,7 @@ def test_constructor_dtype_timedelta64(self):
13321332
td.astype("int32")
13331333

13341334
# this is an invalid casting
1335-
msg = "Could not convert object to NumPy timedelta"
1335+
msg = "Could not convert 'foo' to NumPy timedelta"
13361336
with pytest.raises(ValueError, match=msg):
13371337
Series([timedelta(days=1), "foo"], dtype="m8[ns]")
13381338

pandas/tests/tools/test_to_timedelta.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,10 @@ def test_to_timedelta_invalid(self):
124124
to_timedelta(time(second=1))
125125
assert to_timedelta(time(second=1), errors="coerce") is pd.NaT
126126

127-
msg = "unit abbreviation w/o a number"
127+
msg = "Could not convert 'foo' to NumPy timedelta"
128128
with pytest.raises(ValueError, match=msg):
129129
to_timedelta(["foo", "bar"])
130+
130131
tm.assert_index_equal(
131132
TimedeltaIndex([pd.NaT, pd.NaT]),
132133
to_timedelta(["foo", "bar"], errors="coerce"),

0 commit comments

Comments
 (0)