diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 267780219c74e..d7feb194af11e 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1952,14 +1952,21 @@ def objects_to_datetime64ns( yearfirst=yearfirst, require_iso8601=require_iso8601, ) - except ValueError as e: + except ValueError as err: try: values, tz_parsed = conversion.datetime_to_datetime64(data) # If tzaware, these values represent unix timestamps, so we # return them as i8 to distinguish from wall times return values.view("i8"), tz_parsed except (ValueError, TypeError): - raise e + # GH#10720. If we failed to parse datetime then notify + # that flag errors='coerce' could be used to NaT. + # Trying to distinguish exception based on message. + if "Unknown string format" in err.args[0]: + msg = f"Unknown string format: {err.args[1]}" + msg = f"{msg}. You can coerce to NaT by passing errors='coerce'" + raise ValueError(msg).with_traceback(err.__traceback__) + raise if tz_parsed is not None: # We can take a shortcut since the datetime64 numpy array diff --git a/pandas/core/tools/timedeltas.py b/pandas/core/tools/timedeltas.py index 3e185feaea38e..1f205aff6db0a 100644 --- a/pandas/core/tools/timedeltas.py +++ b/pandas/core/tools/timedeltas.py @@ -113,9 +113,11 @@ def _coerce_scalar_to_timedelta_type(r, unit="ns", errors="raise"): try: result = Timedelta(r, unit) - except ValueError: + except ValueError as err: if errors == "raise": - raise + # GH#10720 + msg = f"{err.args[0]}. You can coerce to NaT by passing errors='coerce'" + raise ValueError(msg).with_traceback(err.__traceback__) elif errors == "ignore": return r diff --git a/pandas/tests/indexes/datetimes/test_tools.py b/pandas/tests/indexes/datetimes/test_tools.py index a6a43697c36dc..6555d4a049a93 100644 --- a/pandas/tests/indexes/datetimes/test_tools.py +++ b/pandas/tests/indexes/datetimes/test_tools.py @@ -480,6 +480,17 @@ def test_to_datetime_unparseable_ignore(self): s = "Month 1, 1999" assert pd.to_datetime(s, errors="ignore") == s + def test_to_datetime_unparseable_raise(self): + # GH#10720 + invalid_data = "Month 1, 1999" + expected_args = ( + f"Unknown string format: {invalid_data}. " + "You can coerce to NaT by passing errors='coerce'" + ) + + with pytest.raises(ValueError, match=expected_args): + pd.to_datetime(invalid_data, errors="raise") + @td.skip_if_windows # `tm.set_timezone` does not work in windows def test_to_datetime_now(self): # See GH#18666 diff --git a/pandas/tests/indexes/timedeltas/test_tools.py b/pandas/tests/indexes/timedeltas/test_tools.py index 223bde8b0e2c2..75534c752f44a 100644 --- a/pandas/tests/indexes/timedeltas/test_tools.py +++ b/pandas/tests/indexes/timedeltas/test_tools.py @@ -111,6 +111,15 @@ def test_to_timedelta_invalid(self): invalid_data, to_timedelta(invalid_data, errors="ignore") ) + # GH#10720 + invalid_data = "some_nonesense" + expected_msg = ( + "unit abbreviation w/o a number. " + "You can coerce to NaT by passing errors='coerce'" + ) + with pytest.raises(ValueError, match=expected_msg): + pd.to_timedelta(invalid_data, errors="raise") + def test_to_timedelta_via_apply(self): # GH 5458 expected = Series([np.timedelta64(1, "s")])