Skip to content

Commit c2b2a49

Browse files
authored
REF: avoid catching and re-raising in datetime parsing (#50629)
1 parent e7e3676 commit c2b2a49

File tree

4 files changed

+29
-34
lines changed

4 files changed

+29
-34
lines changed

pandas/_libs/tslibs/conversion.pyx

+23-31
Original file line numberDiff line numberDiff line change
@@ -520,43 +520,35 @@ cdef _TSObject _convert_str_to_tsobject(object ts, tzinfo tz, str unit,
520520
)
521521
if not string_to_dts_failed:
522522
reso = get_supported_reso(out_bestunit)
523-
try:
524-
check_dts_bounds(&dts, reso)
525-
if out_local == 1:
526-
return _create_tsobject_tz_using_offset(
527-
dts, out_tzoffset, tz, reso
523+
check_dts_bounds(&dts, reso)
524+
if out_local == 1:
525+
return _create_tsobject_tz_using_offset(
526+
dts, out_tzoffset, tz, reso
527+
)
528+
else:
529+
ival = npy_datetimestruct_to_datetime(reso, &dts)
530+
if tz is not None:
531+
# shift for _localize_tso
532+
ival = tz_localize_to_utc_single(
533+
ival, tz, ambiguous="raise", nonexistent=None, creso=reso
528534
)
529-
else:
530-
ival = npy_datetimestruct_to_datetime(reso, &dts)
531-
if tz is not None:
532-
# shift for _localize_tso
533-
ival = tz_localize_to_utc_single(
534-
ival, tz, ambiguous="raise", nonexistent=None, creso=reso
535-
)
536-
obj = _TSObject()
537-
obj.dts = dts
538-
obj.value = ival
539-
obj.creso = reso
540-
maybe_localize_tso(obj, tz, obj.creso)
541-
return obj
542-
543-
except OutOfBoundsDatetime:
544-
# GH#19382 for just-barely-OutOfBounds falling back to dateutil
545-
# parser will return incorrect result because it will ignore
546-
# nanoseconds
547-
raise
548-
549-
except ValueError:
550-
# Fall through to parse_datetime_string
551-
pass
535+
obj = _TSObject()
536+
obj.dts = dts
537+
obj.value = ival
538+
obj.creso = reso
539+
maybe_localize_tso(obj, tz, obj.creso)
540+
return obj
552541

553542
try:
554-
# TODO: use the one that returns reso
555543
dt = parse_datetime_string(
556544
ts, dayfirst=dayfirst, yearfirst=yearfirst
557545
)
558-
except (ValueError, OverflowError) as err:
559-
raise ValueError("could not convert string to Timestamp") from err
546+
except ValueError as err:
547+
if "out of range for month" in str(err):
548+
# dateutil raised when constructing a datetime object,
549+
# let's give a nicer exception message
550+
raise ValueError("could not convert string to Timestamp") from err
551+
raise
560552

561553
return convert_datetime_to_tsobject(dt, tz)
562554

pandas/tests/indexes/datetimes/test_date_range.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ def test_misc(self):
980980
def test_date_parse_failure(self):
981981
badly_formed_date = "2007/100/1"
982982

983-
msg = "could not convert string to Timestamp"
983+
msg = "Unknown string format: 2007/100/1"
984984
with pytest.raises(ValueError, match=msg):
985985
Timestamp(badly_formed_date)
986986

pandas/tests/io/pytables/test_select.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,10 @@ def test_query_compare_column_type(setup_path):
939939
v = "a"
940940
for col in ["int", "float", "real_date"]:
941941
query = f"{col} {op} v"
942-
msg = "could not convert string to "
942+
if col == "real_date":
943+
msg = 'Given date string "a" not likely a datetime'
944+
else:
945+
msg = "could not convert string to "
943946
with pytest.raises(ValueError, match=msg):
944947
store.select("test", where=query)
945948

pandas/tests/scalar/timestamp/test_constructors.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ def test_constructor_nanosecond(self, result):
429429
@pytest.mark.parametrize("z", ["Z0", "Z00"])
430430
def test_constructor_invalid_Z0_isostring(self, z):
431431
# GH 8910
432-
msg = "could not convert string to Timestamp"
432+
msg = f"Unknown string format: 2014-11-02 01:00{z}"
433433
with pytest.raises(ValueError, match=msg):
434434
Timestamp(f"2014-11-02 01:00{z}")
435435

0 commit comments

Comments
 (0)