You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Given a month with 32 days, dateparser fails with some years but parses with others #868
from dateparser import parse
# None
parse("32 DEC 95", date_formats=["%d %b %y"])
and
from dateparser import parse
# 2032-12-10 00:00:00
parse("32 DEC 10", date_formats=["%d %b %y"])
In both cases December with 32 days is given. In the first case, suddenly the 32 becomes the year, even though date_formats specifies a different format.
Expected behavior
I would expect both of the parsed dates to be None
For the remaining date_formats part, separate from the DATE_ORDER work in #1443, the current source treats supplied formats as attempts rather than an exclusive allowlist: after those attempts fail, get_date_data() continues through the enabled parsers.
A regression for an exclusive-format contract can restrict that second stage:
The expected result is None; add 32 DEC 95 as the same invalid-day case and 31 DEC 10 / 31 DEC 95 as positive controls. This tests calendar validity without allowing a failed day token to become the year. It also gives the documentation a concrete distinction between preferred formats and permitted formats.
I maintain DateParser Kotlin; its MIT invalid-calendar regression fixtures illustrate that rejection boundary. They are a source/test reference, not interchangeable Python APIs. I haven't run this example against dateparser.
Thanks again for the review of #1443. This is where I ended up on the date_formats half that we left for this issue (checked on current master, ac088237).
Where the wrong dates come from. Not from the formats: when no format matches, the string goes on to the other parsers, which read the numbers in a locale's order. That is how parse("32 DEC 10", date_formats=["%d %b %y"]) becomes 2032-12-10, and, without languages, "31 FEB 10" becomes 2031-02-10 (read by sv, which is year-first). The fallback is old and intended (formats first, then everything else), but it was never documented. The docstring change in #1440 now says it.
What exists today.
STRICT_DATE_ORDER with a DATE_ORDER that matches the format: the issue's example gives None with {"DATE_ORDER": "DMY", "STRICT_DATE_ORDER": "year"}, and "all" also stops the day/month swap. It requires DATE_ORDER (it raises without), so it does not help when there is no single order, and date_formats alone is not covered.
PARSERS=["custom-formats"] also gives None (for 32 DEC 10 and 32 DEC 95, as @Alox1d suggested in the last comment), but it switches off every other parser: timestamps, relative dates, free-form dates.
What remains. In a grid of 12 formats and 4,136 strings, 744 of the 2,828 invalid ones (26%) still return a date with date_formats alone.
Proposal I tried. The idea from the #1443 thread: skip the fallback when the string has the shape of one of the formats (strptime with every digit replaced by 1). It is small (34 lines, no new setting) and returns None for the issue's examples. As a default it is too broad, though. In a differential run of 812,514 calls it only turned dates into None (never a date into another date, no new exceptions), but that is 13% of the dates master returns. Some of those are valid day/month swaps ("12/31/2020" with %d/%m/%Y is 2020-12-31 today), and in my first version plain years and Unix timestamps with digit-only formats too. A narrower rule (not when swapping day and month would parse, never for digit-only strings) removes most of that and keeps nearly all the out-of-range cases.
Question. Given the opt-in rule from #1443, which would you prefer?
Thanks for the detailed check. I'd go with (a) for the docs now and (b) for a behavior change, keeping the current default. The compatibility cases you found, together with the opt-in direction in #1443, make (c) hard to justify.
For (b), I'd document the exact rejection boundary, including the day/month-swap and digit-only exceptions. The tests should include 32 DEC 10 / 32 DEC 95, their valid 31 DEC counterparts, and automatic language detection as well as explicit languages. Your 31 FEB 10 example shows why the locale fallback matters here.
A PR with the narrower rule and its remaining counterexamples would make it easier to review. Agreed on keeping this issue open.
The opt-in rule (a STRICT_DATE_FORMATS setting, default unchanged), with the docs, the 32 DEC 10 / 32 DEC 95 / 31 DEC tests and its remaining counterexamples, is in #1547; the docstring text is still #1440.
Activity
noviluni commentedon Jan 19, 2021
It seems a bug. I even tried with "DATE_ORDER" but it gives a result too 😮 🤔
I will check it.
Keep only the DATE_ORDER check of #868
Do not read an invalid day as the year under an explicit DATE_ORDER (#…
Make the DATE_ORDER check of #868 opt-in with STRICT_DATE_ORDER
Add a STRICT_DATE_ORDER setting so that an invalid day is not read as…
Add a STRICT_DATE_ORDER setting to enforce the year position or the w…
Alox1d commentedon Oct 15, 2026
For the remaining
date_formatspart, separate from theDATE_ORDERwork in #1443, the current source treats supplied formats as attempts rather than an exclusive allowlist: after those attempts fail,get_date_data()continues through the enabled parsers.A regression for an exclusive-format contract can restrict that second stage:
The expected result is
None; add32 DEC 95as the same invalid-day case and31 DEC 10/31 DEC 95as positive controls. This tests calendar validity without allowing a failed day token to become the year. It also gives the documentation a concrete distinction between preferred formats and permitted formats.I maintain DateParser Kotlin; its MIT invalid-calendar regression fixtures illustrate that rejection boundary. They are a source/test reference, not interchangeable Python APIs. I haven't run this example against dateparser.
serhii73 commentedon Oct 16, 2026
Thanks again for the review of #1443. This is where I ended up on the
date_formatshalf that we left for this issue (checked on current master,ac088237).Where the wrong dates come from. Not from the formats: when no format matches, the string goes on to the other parsers, which read the numbers in a locale's order. That is how
parse("32 DEC 10", date_formats=["%d %b %y"])becomes 2032-12-10, and, withoutlanguages,"31 FEB 10"becomes 2031-02-10 (read bysv, which is year-first). The fallback is old and intended (formats first, then everything else), but it was never documented. The docstring change in #1440 now says it.What exists today.
STRICT_DATE_ORDERwith aDATE_ORDERthat matches the format: the issue's example givesNonewith{"DATE_ORDER": "DMY", "STRICT_DATE_ORDER": "year"}, and"all"also stops the day/month swap. It requiresDATE_ORDER(it raises without), so it does not help when there is no single order, anddate_formatsalone is not covered.PARSERS=["custom-formats"]also givesNone(for32 DEC 10and32 DEC 95, as @Alox1d suggested in the last comment), but it switches off every other parser: timestamps, relative dates, free-form dates.What remains. In a grid of 12 formats and 4,136 strings, 744 of the 2,828 invalid ones (26%) still return a date with
date_formatsalone.Proposal I tried. The idea from the #1443 thread: skip the fallback when the string has the shape of one of the formats (
strptimewith every digit replaced by1). It is small (34 lines, no new setting) and returnsNonefor the issue's examples. As a default it is too broad, though. In a differential run of 812,514 calls it only turned dates intoNone(never a date into another date, no new exceptions), but that is 13% of the dates master returns. Some of those are valid day/month swaps ("12/31/2020"with%d/%m/%Yis 2020-12-31 today), and in my first version plain years and Unix timestamps with digit-only formats too. A narrower rule (not when swapping day and month would parse, never for digit-only strings) removes most of that and keeps nearly all the out-of-range cases.Question. Given the opt-in rule from #1443, which would you prefer?
STRICT_DATE_ORDERwithDATE_ORDER);I can send a PR for (b) or (c). I would keep this issue open until we decide.
Alox1d commentedon Oct 17, 2026
Thanks for the detailed check. I'd go with (a) for the docs now and (b) for a behavior change, keeping the current default. The compatibility cases you found, together with the opt-in direction in #1443, make (c) hard to justify.
For (b), I'd document the exact rejection boundary, including the day/month-swap and digit-only exceptions. The tests should include
32 DEC 10/32 DEC 95, their valid31 DECcounterparts, and automatic language detection as well as explicit languages. Your31 FEB 10example shows why the locale fallback matters here.A PR with the narrower rule and its remaining counterexamples would make it easier to review. Agreed on keeping this issue open.
serhii73 commentedon Oct 19, 2026
The opt-in rule (a
STRICT_DATE_FORMATSsetting, default unchanged), with the docs, the32 DEC 10/32 DEC 95/31 DECtests and its remaining counterexamples, is in #1547; the docstring text is still #1440.Document how date_formats falls back to the other parsers (#1549)