Skip to content

Stop French "sept" being simplified to 7 when it means September - #1353

Open
DMZ22 wants to merge 1 commit into
scrapinghub:masterfrom
DMZ22:fr-sept-month-abbreviation
Open

Stop French "sept" being simplified to 7 when it means September#1353
DMZ22 wants to merge 1 commit into
scrapinghub:masterfrom
DMZ22:fr-sept-month-abbreviation

Conversation

@DMZ22

@DMZ22 DMZ22 commented Jul 24, 2026

Copy link
Copy Markdown

Closes #1285.

sept is both the abbreviation for septembre and the French word for seven. Simplifications are applied to the whole string in Locale.translate() before the dictionary is consulted, so by the time month names are looked up the token sept no longer exists — it is already 7. The month translation can never win.

parse("1 sept. 2024", locales=["fr"])   ->  2024-07-01     # July
parse("1 septembre 2024", locales=["fr"]) ->  2024-09-01
parse("1 sep. 2024", locales=["fr"])    ->  2024-09-01

The dot is not the discriminator. sanitize_date() runs RE_SANITIZE_PERIOD.sub("", …) before the locale is consulted, so 1 sept. 2024 and 1 sept 2024 are the same string by then — both were wrong. A fix keyed on sept. cannot work.

I also want to flag why this looks fine in casual testing: without an explicit locale it already returns September, because language detection picks en and the French simplification never runs. The existing case at tests/test_date_parser.py:63 ("11 sept. 2014") passes for exactly that reason. Only the locale-pinned path — the one you use when you know the language — is broken.

The change

Only simplify sept to 7 where it is a quantity: followed by a French duration unit or a clock time. The unit list is taken from the French data itself (année/ans/an, mois/m, semaine/sem, jour/j, heure/h, minute/min, seconde/s).

One subtlety worth its own note. a is a valid abbreviation for année, but normalize_unicode() runs before simplification, so the preposition à has already become a by then. Accepting a bare a as a unit therefore re-breaks 3 sept à 14h30; rejecting it outright breaks il y a sept a. The rule I settled on accepts a as a unit only when no number follows it, which keeps both:

"3 sept à 14h30"   ->  2026-09-03 14:30      # month
"il y a sept a"    ->  2019-01-15            # seven years ago

Verification

The regression surface here is the real risk, and it is almost entirely untestedtests/test_freshness_date_parser.py has no French cases at all, so simply deleting the sept: '7' entry would leave CI green while silently breaking every "seven " phrase. I checked that explicitly: I built a 30-phrase set of cardinal-seven inputs (il y a sept jours, sept semaines, dans sept heures, sept:30, sept ans et 3 mois, the single-letter forms, …), recorded their output before the change, and compared after.

  • 16 month phrasings that returned July/January now return September.
  • 0 of 30 cardinal-seven phrases changed.
  • Full suite: pytest tests --ignore=tests/test_date.py gives 3 failed / 23793 passed before and 3 failed / 23802 passed after — same three failures (test_parse_negative_timestamp_*, a Windows-only OSError in datetime.fromtimestamp, unrelated), plus the 9 new params.
  • tests/test_dateparser_data_integrity.py passes, so the regenerated fr.py matches the YAML.
  • Reverting just the two data files while keeping the tests fails 4 of the new params, so they do guard the change; the 5 cardinal params pass either way, deliberately, since their job is to catch over-correction.
  • ruff and ruff-format (v0.9.3, matching .pre-commit-config.yaml) are clean.

fr.py was regenerated with dateparser_scripts/write_complete_data.py rather than hand-edited.

"sept" is both the abbreviation for "septembre" and the French word for
seven, and simplifications are applied to the whole string before month
names are looked up, so the number always won: with French pinned,
"1 sept. 2024" parsed as 1 July 2024.

The trailing dot cannot be used to tell the two apart, because
sanitize_date() strips it before the locale is consulted -- "1 sept 2024"
was equally wrong. Instead, only simplify "sept" to 7 where it is a
quantity, that is when it is followed by a French duration unit or by a
clock time.

"a" (for "annee") is accepted as a unit only when no number follows it,
because the preposition "a" loses its accent during normalization and
would otherwise swallow the month in "3 sept a 14h30".

Regenerated fr.py with dateparser_scripts/write_complete_data.py.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parser confuses sept (7) with sept. (septembre) in French

2 participants