Repository navigation
fix(dtypes): a time of day no longer defeats the dayfirst="auto" quarantine - #506
Merged
Merged
Conversation
…antine
Under the default dayfirst="auto", day/month-ambiguous dates are documented
to be quarantined for review, never read in an inferred order (config.py).
A bare "05/01/2021" was. But "05/01/2021 00:00" was read as 1 May -- silently,
reported as a plain "converted to datetime64[ns]", no quarantine, no
ambiguity note, no warning. On a day-first export every date landed in the
wrong month. Affects every supported pandas version.
_AMBIGUOUS_DATE was anchored at $ straight after the year, so any time
suffix stopped the match; the value then reached the parser, where "auto"
becomes month-first.
The detector now searches for the numeric date token anywhere in the value
rather than matching the whole string, and a value is ambiguous if any of
its tokens is. A first version that listed allowed time suffixes still let
six shapes through ("05/01/2021, 10:00", "Mon 05/01/2021", "05/01/2021.",
"05/01/2021 10h", "05/01/2021 at 10:00", ...): any list of decorations is
incomplete, so a whole-string detector fails open. Searching fails closed --
the worst case is over-quarantine, which is reviewable.
The finance domain validator already treated timed values as ambiguous; the
core dtype step now agrees with it.
tests/test_dayfirst_auto_timed.py: 28 tests; 17 fail without this change on
both py3.12/pandas 2.3.3 and py3.9/pandas 1.5.3.
Contributor
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
FreshData benchmark report —
|
| fixture | n_rows | n_cols | p50 s | p95 s | peak MB | repair % | false-repair % | preserve % | trust | monotonic | export % |
|---|
Authored-code reduction (Metric 6)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
Under the default
dayfirst="auto", day/month-ambiguous dates are documented to be quarantined for review, never read in an inferred order (config.py). A bare date is. Add a time of day and it isn't:The timed column is read month-first, and the report says only
converted to datetime64[ns]: no quarantine, no ambiguity note, no warning. Every value is ambiguous (both tokens ≤ 12), the exact case"auto"exists to protect. On a day-first export, every date lands in the wrong month. This affects every supported pandas version.Cause
steps/dtypes.py:The pattern is anchored at
$straight after the year, so any time suffix stops the match. The value is then never quarantined and reaches_parse_datetimewithdayfirst = config.dayfirst if isinstance(config.dayfirst, bool) else False, so"auto"silently becomes month-first for any value the detector misses.Fix
Search for the numeric date token anywhere in the value instead of matching the whole string; a value is ambiguous if any of its tokens is:
No time, weekday, AM/PM marker or UTC offset around the token says which part is the month.
Why search rather than widen the anchor. A first version widened the anchor to allow a list of time suffixes. It passed its own tests, but a probe of shapes outside that list found six still read month-first:
"05/01/2021, 10:00","Mon 05/01/2021","Mon 05/01/2021 10:00","05/01/2021.","05/01/2021 10h","05/01/2021 at 10:00". Any list of decorations pandas will parse is incomplete, so a whole-string detector fails open, and each missing shape becomes a silent wrong date. Searching fails closed: the worst case is over-quarantine, which is reviewable because the original is kept incoerced_cells.The finance domain validator already treats timed values as ambiguous (its own pattern ends in
(?!\d)), so the core dtype step now agrees with it.Tests
tests/test_dayfirst_auto_timed.py, 28 tests:13/01/2021 10:00) still parsedayfirst=True/Falsestill resolve timed values both wayscoerced_cellsand a day/month-ambiguity note20210501,105/01/2021,05/01/2021123, certain dates17 fail without the
src/change, on both py3.12 / pandas 2.3.3 and py3.9 / pandas 1.5.3. The 11 that pass either way are controls.Checked and unaffected:
_PARTIAL_ISO_DATEhas the same^…$anchoring, but"2025-01 10:00"is still left missing, not given an invented day.Verification
Full suite (
-m "not online and not large") ond65e896(after #504 and #505) + this change:ruff checkclean.Compatibility impact
Output changes for columns of numeric dates with anything around them (a time, weekday, offset or trailing punctuation) where both day and month are ≤ 12, cleaned with the default
dayfirst="auto". These values are now quarantined — set to missing, with the original inreport.coerced_cells— exactly as the same dates without decoration always were, and a column made entirely of them stays text. Previously they were converted month-first. To convert them, state the order withdayfirst=Trueordayfirst=False. Unambiguous values and explicitdayfirstsettings are unchanged.