Skip to content

Commit b7b5193

Browse files
author
MarcoGorelli
committed
factor out iso year/week/weekday check, improve error message and
coverage
1 parent e413b91 commit b7b5193

File tree

3 files changed

+61
-22
lines changed

3 files changed

+61
-22
lines changed

doc/source/whatsnew/v2.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,7 @@ Datetimelike
786786
- Bug in :func:`to_datetime` was raising ``ValueError`` when parsing :class:`Timestamp`, ``datetime.datetime``, ``datetime.date``, or ``np.datetime64`` objects when non-ISO8601 ``format`` was passed (:issue:`49298`, :issue:`50036`)
787787
- Bug in :func:`to_datetime` was raising ``ValueError`` when parsing empty string and non-ISO8601 format was passed. Now, empty strings will be parsed as :class:`NaT`, for compatibility with how is done for ISO8601 formats (:issue:`50251`)
788788
- Bug in :class:`Timestamp` was showing ``UserWarning``, which was not actionable by users, when parsing non-ISO8601 delimited date strings (:issue:`50232`)
789+
- Bug in :func:`to_datetime` was showing misleading ``ValueError`` when parsing dates with format containing ISO week directive and ISO weekday directive (:issue:`50308`)
789790
-
790791

791792
Timedelta

pandas/_libs/tslibs/strptime.pyx

+34-20
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,40 @@ def array_strptime(
121121
raise ValueError("Cannot use '%W' or '%U' without day and year")
122122
elif "%Z" in fmt and "%z" in fmt:
123123
raise ValueError("Cannot parse both %Z and %z")
124+
elif "%G" in fmt and (
125+
"%V" not in fmt
126+
or not (
127+
"%A" in fmt
128+
or "%A" in fmt
129+
or "%a" in fmt
130+
or "%w" in fmt
131+
or "%u" in fmt
132+
)
133+
):
134+
raise ValueError("ISO year directive '%G' must be used with "
135+
"the ISO week directive '%V' and a weekday "
136+
"directive '%A', '%a', '%w', or '%u'.")
137+
elif "%j" in fmt and "%G" in fmt:
138+
raise ValueError("Day of the year directive '%j' is not "
139+
"compatible with ISO year directive '%G'. "
140+
"Use '%Y' instead.")
141+
elif ("%V" in fmt and "%Y" in fmt):
142+
raise ValueError("ISO week directive '%V' is incompatible with "
143+
"the year directive '%Y'. Use the ISO year "
144+
"'%G' instead.")
145+
elif "%V" in fmt and (
146+
"%G" not in fmt
147+
or not (
148+
"%A" in fmt
149+
or "%A" in fmt
150+
or "%a" in fmt
151+
or "%w" in fmt
152+
or "%u" in fmt
153+
)
154+
):
155+
raise ValueError("ISO week directive '%V' must be used with "
156+
"the ISO year directive '%G' and a weekday "
157+
"directive '%A', '%a', '%w', or '%u'.")
124158

125159
global _TimeRE_cache, _regex_cache
126160
with _cache_lock:
@@ -328,26 +362,6 @@ def array_strptime(
328362
weekday = int(found_dict["u"])
329363
weekday -= 1
330364

331-
# don't assume default values for ISO week/year
332-
if iso_year != -1:
333-
if iso_week == -1 or weekday == -1:
334-
raise ValueError("ISO year directive '%G' must be used with "
335-
"the ISO week directive '%V' and a weekday "
336-
"directive '%A', '%a', '%w', or '%u'.")
337-
if julian != -1:
338-
raise ValueError("Day of the year directive '%j' is not "
339-
"compatible with ISO year directive '%G'. "
340-
"Use '%Y' instead.")
341-
elif year != -1 and week_of_year == -1 and iso_week != -1:
342-
if weekday == -1:
343-
raise ValueError("ISO week directive '%V' must be used with "
344-
"the ISO year directive '%G' and a weekday "
345-
"directive '%A', '%a', '%w', or '%u'.")
346-
else:
347-
raise ValueError("ISO week directive '%V' is incompatible with "
348-
"the year directive '%Y'. Use the ISO year "
349-
"'%G' instead.")
350-
351365
# If we know the wk of the year and what day of that wk, we can figure
352366
# out the Julian day of the year.
353367
if julian == -1 and weekday != -1:

pandas/tests/tools/test_to_datetime.py

+26-2
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,8 @@ def test_to_datetime_iso_week_year_format(self, s, _format, dt):
629629
"msg, s, _format",
630630
[
631631
[
632-
"ISO week directive '%V' must be used with the ISO year directive "
633-
"'%G' and a weekday directive '%A', '%a', '%w', or '%u'.",
632+
"ISO week directive '%V' is incompatible with the year directive "
633+
"'%Y'. Use the ISO year '%G' instead.",
634634
"1999 50",
635635
"%Y %V",
636636
],
@@ -706,6 +706,30 @@ def test_to_datetime_iso_week_year_format(self, s, _format, dt):
706706
"20",
707707
"%V",
708708
],
709+
[
710+
"ISO week directive '%V' must be used with the ISO year directive "
711+
"'%G' and a weekday directive '%A', '%a', '%w', or '%u'.",
712+
"1999 51 Sunday",
713+
"%V %A",
714+
],
715+
[
716+
"ISO week directive '%V' must be used with the ISO year directive "
717+
"'%G' and a weekday directive '%A', '%a', '%w', or '%u'.",
718+
"1999 51 Sun",
719+
"%V %a",
720+
],
721+
[
722+
"ISO week directive '%V' must be used with the ISO year directive "
723+
"'%G' and a weekday directive '%A', '%a', '%w', or '%u'.",
724+
"1999 51 1",
725+
"%V %w",
726+
],
727+
[
728+
"ISO week directive '%V' must be used with the ISO year directive "
729+
"'%G' and a weekday directive '%A', '%a', '%w', or '%u'.",
730+
"1999 51 1",
731+
"%V %u",
732+
],
709733
],
710734
)
711735
def test_error_iso_week_year(self, msg, s, _format):

0 commit comments

Comments
 (0)