Skip to content

Commit d20c02b

Browse files
authored
BUG: misleading message when using to_datetime with format='%V %a' (#50309)
* factor out iso year/week/weekday check, improve error message and coverage * add extra test * dedupe Co-authored-by: MarcoGorelli <>
1 parent bf05f35 commit d20c02b

File tree

3 files changed

+72
-23
lines changed

3 files changed

+72
-23
lines changed

doc/source/whatsnew/v2.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,7 @@ Datetimelike
792792
- 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`)
793793
- 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`)
794794
- Bug in :class:`Timestamp` was showing ``UserWarning``, which was not actionable by users, when parsing non-ISO8601 delimited date strings (:issue:`50232`)
795+
- Bug in :func:`to_datetime` was showing misleading ``ValueError`` when parsing dates with format containing ISO week directive and ISO weekday directive (:issue:`50308`)
795796
-
796797

797798
Timedelta

pandas/_libs/tslibs/strptime.pyx

+32-20
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,38 @@ 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 "%j" in fmt and "%G" in fmt:
125+
raise ValueError("Day of the year directive '%j' is not "
126+
"compatible with ISO year directive '%G'. "
127+
"Use '%Y' instead.")
128+
elif "%G" in fmt and (
129+
"%V" not in fmt
130+
or not (
131+
"%A" in fmt
132+
or "%a" in fmt
133+
or "%w" in fmt
134+
or "%u" in fmt
135+
)
136+
):
137+
raise ValueError("ISO year directive '%G' must be used with "
138+
"the ISO week directive '%V' and a weekday "
139+
"directive '%A', '%a', '%w', or '%u'.")
140+
elif "%V" in fmt and "%Y" in fmt:
141+
raise ValueError("ISO week directive '%V' is incompatible with "
142+
"the year directive '%Y'. Use the ISO year "
143+
"'%G' instead.")
144+
elif "%V" in fmt and (
145+
"%G" not in fmt
146+
or not (
147+
"%A" in fmt
148+
or "%a" in fmt
149+
or "%w" in fmt
150+
or "%u" in fmt
151+
)
152+
):
153+
raise ValueError("ISO week directive '%V' must be used with "
154+
"the ISO year directive '%G' and a weekday "
155+
"directive '%A', '%a', '%w', or '%u'.")
124156

125157
global _TimeRE_cache, _regex_cache
126158
with _cache_lock:
@@ -328,26 +360,6 @@ def array_strptime(
328360
weekday = int(found_dict["u"])
329361
weekday -= 1
330362

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-
351363
# If we know the wk of the year and what day of that wk, we can figure
352364
# out the Julian day of the year.
353365
if julian == -1 and weekday != -1:

pandas/tests/tools/test_to_datetime.py

+39-3
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,10 +706,46 @@ 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+
],
733+
[
734+
"Day of the year directive '%j' is not compatible with ISO year "
735+
"directive '%G'. Use '%Y' instead.",
736+
"1999 50",
737+
"%G %j",
738+
],
739+
[
740+
"ISO week directive '%V' must be used with the ISO year directive "
741+
"'%G' and a weekday directive '%A', '%a', '%w', or '%u'.",
742+
"20 Monday",
743+
"%V %A",
744+
],
709745
],
710746
)
711747
def test_error_iso_week_year(self, msg, s, _format):
712-
# See GH#16607
748+
# See GH#16607, #50308
713749
# This test checks for errors thrown when giving the wrong format
714750
# However, as discussed on PR#25541, overriding the locale
715751
# causes a different error to be thrown due to the format being

0 commit comments

Comments
 (0)