diff --git a/pandas/_libs/tslibs/conversion.pyx b/pandas/_libs/tslibs/conversion.pyx index 1104c1f8e67a9..33815aee8b795 100644 --- a/pandas/_libs/tslibs/conversion.pyx +++ b/pandas/_libs/tslibs/conversion.pyx @@ -520,43 +520,35 @@ cdef _TSObject _convert_str_to_tsobject(object ts, tzinfo tz, str unit, ) if not string_to_dts_failed: reso = get_supported_reso(out_bestunit) - try: - check_dts_bounds(&dts, reso) - if out_local == 1: - return _create_tsobject_tz_using_offset( - dts, out_tzoffset, tz, reso + check_dts_bounds(&dts, reso) + if out_local == 1: + return _create_tsobject_tz_using_offset( + dts, out_tzoffset, tz, reso + ) + else: + ival = npy_datetimestruct_to_datetime(reso, &dts) + if tz is not None: + # shift for _localize_tso + ival = tz_localize_to_utc_single( + ival, tz, ambiguous="raise", nonexistent=None, creso=reso ) - else: - ival = npy_datetimestruct_to_datetime(reso, &dts) - if tz is not None: - # shift for _localize_tso - ival = tz_localize_to_utc_single( - ival, tz, ambiguous="raise", nonexistent=None, creso=reso - ) - obj = _TSObject() - obj.dts = dts - obj.value = ival - obj.creso = reso - maybe_localize_tso(obj, tz, obj.creso) - return obj - - except OutOfBoundsDatetime: - # GH#19382 for just-barely-OutOfBounds falling back to dateutil - # parser will return incorrect result because it will ignore - # nanoseconds - raise - - except ValueError: - # Fall through to parse_datetime_string - pass + obj = _TSObject() + obj.dts = dts + obj.value = ival + obj.creso = reso + maybe_localize_tso(obj, tz, obj.creso) + return obj try: - # TODO: use the one that returns reso dt = parse_datetime_string( ts, dayfirst=dayfirst, yearfirst=yearfirst ) - except (ValueError, OverflowError) as err: - raise ValueError("could not convert string to Timestamp") from err + except ValueError as err: + if "out of range for month" in str(err): + # dateutil raised when constructing a datetime object, + # let's give a nicer exception message + raise ValueError("could not convert string to Timestamp") from err + raise return convert_datetime_to_tsobject(dt, tz) diff --git a/pandas/tests/indexes/datetimes/test_date_range.py b/pandas/tests/indexes/datetimes/test_date_range.py index 14bfb14d27239..ec9a6842dc91e 100644 --- a/pandas/tests/indexes/datetimes/test_date_range.py +++ b/pandas/tests/indexes/datetimes/test_date_range.py @@ -980,7 +980,7 @@ def test_misc(self): def test_date_parse_failure(self): badly_formed_date = "2007/100/1" - msg = "could not convert string to Timestamp" + msg = "Unknown string format: 2007/100/1" with pytest.raises(ValueError, match=msg): Timestamp(badly_formed_date) diff --git a/pandas/tests/io/pytables/test_select.py b/pandas/tests/io/pytables/test_select.py index 76d5cc5672e40..b0c9b85e7ad05 100644 --- a/pandas/tests/io/pytables/test_select.py +++ b/pandas/tests/io/pytables/test_select.py @@ -939,7 +939,10 @@ def test_query_compare_column_type(setup_path): v = "a" for col in ["int", "float", "real_date"]: query = f"{col} {op} v" - msg = "could not convert string to " + if col == "real_date": + msg = 'Given date string "a" not likely a datetime' + else: + msg = "could not convert string to " with pytest.raises(ValueError, match=msg): store.select("test", where=query) diff --git a/pandas/tests/scalar/timestamp/test_constructors.py b/pandas/tests/scalar/timestamp/test_constructors.py index 4143e52bbb7ed..aa5a55e6ca39d 100644 --- a/pandas/tests/scalar/timestamp/test_constructors.py +++ b/pandas/tests/scalar/timestamp/test_constructors.py @@ -429,7 +429,7 @@ def test_constructor_nanosecond(self, result): @pytest.mark.parametrize("z", ["Z0", "Z00"]) def test_constructor_invalid_Z0_isostring(self, z): # GH 8910 - msg = "could not convert string to Timestamp" + msg = f"Unknown string format: 2014-11-02 01:00{z}" with pytest.raises(ValueError, match=msg): Timestamp(f"2014-11-02 01:00{z}")