Skip to content

Commit 1fc2213

Browse files
BUG: Timestamp parsing creating invalid object (#50668)
* BUG: Timestamp parsing creating invalid object * whatsnew * reword * Update doc/source/whatsnew/v2.0.0.rst Co-authored-by: Matthew Roeschke <[email protected]>
1 parent 1840423 commit 1fc2213

File tree

4 files changed

+31
-4
lines changed

4 files changed

+31
-4
lines changed

doc/source/whatsnew/v2.0.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,8 @@ Timezones
914914
- Bug in :meth:`Series.astype` and :meth:`DataFrame.astype` with object-dtype containing multiple timezone-aware ``datetime`` objects with heterogeneous timezones to a :class:`DatetimeTZDtype` incorrectly raising (:issue:`32581`)
915915
- Bug in :func:`to_datetime` was failing to parse date strings with timezone name when ``format`` was specified with ``%Z`` (:issue:`49748`)
916916
- Better error message when passing invalid values to ``ambiguous`` parameter in :meth:`Timestamp.tz_localize` (:issue:`49565`)
917+
- Bug in string parsing incorrectly allowing a :class:`Timestamp` to be constructed with an invalid timezone, which would raise when trying to print (:issue:`50668`)
918+
-
917919

918920
Numeric
919921
^^^^^^^

pandas/_libs/tslibs/parsing.pyx

+13
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,19 @@ def parse_datetime_string(
304304
raise OutOfBoundsDatetime(
305305
f'Parsing "{date_string}" to datetime overflows'
306306
) from err
307+
if dt.tzinfo is not None:
308+
# dateutil can return a datetime with a tzoffset outside of (-24H, 24H)
309+
# bounds, which is invalid (can be constructed, but raises if we call
310+
# str(dt)). Check that and raise here if necessary.
311+
try:
312+
dt.utcoffset()
313+
except ValueError as err:
314+
# offset must be a timedelta strictly between -timedelta(hours=24)
315+
# and timedelta(hours=24)
316+
raise ValueError(
317+
f'Parsed string "{date_string}" gives an invalid tzoffset, '
318+
"which must be between -timedelta(hours=24) and timedelta(hours=24)"
319+
)
307320

308321
return dt
309322

pandas/tests/scalar/timestamp/test_constructors.py

+10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@
2424

2525

2626
class TestTimestampConstructors:
27+
def test_construct_from_string_invalid_raises(self):
28+
# dateutil (weirdly) parses "200622-12-31" as
29+
# datetime(2022, 6, 20, 12, 0, tzinfo=tzoffset(None, -111600)
30+
# which besides being mis-parsed, is a tzoffset that will cause
31+
# str(ts) to raise ValueError. Ensure we raise in the constructor
32+
# instead.
33+
# see test_to_datetime_malformed_raise for analogous to_datetime test
34+
with pytest.raises(ValueError, match="gives an invalid tzoffset"):
35+
Timestamp("200622-12-31")
36+
2737
def test_constructor_from_iso8601_str_with_offset_reso(self):
2838
# GH#49737
2939
ts = Timestamp("2016-01-01 04:05:06-01:00")

pandas/tests/tools/test_to_datetime.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1561,12 +1561,14 @@ def test_to_datetime_malformed_no_raise(self, errors, expected):
15611561
def test_to_datetime_malformed_raise(self):
15621562
# GH 48633
15631563
ts_strings = ["200622-12-31", "111111-24-11"]
1564+
msg = (
1565+
'Parsed string "200622-12-31" gives an invalid tzoffset, which must '
1566+
r"be between -timedelta\(hours=24\) and timedelta\(hours=24\), "
1567+
"at position 0"
1568+
)
15641569
with pytest.raises(
15651570
ValueError,
1566-
match=(
1567-
r"^offset must be a timedelta strictly between "
1568-
r"-timedelta\(hours=24\) and timedelta\(hours=24\)., at position 0$"
1569-
),
1571+
match=msg,
15701572
):
15711573
with tm.assert_produces_warning(
15721574
UserWarning, match="Could not infer format"

0 commit comments

Comments
 (0)