Repository navigation
Conversation
There was a problem hiding this comment.
🔵 Needs a closer look
It is a behavioral change that rejects dates parse_date() previously accepted, which could affect downstream callers and warrants final human sign-off.
No open issues 🎉
What changed in this PR
This PR makes humanfriendly.parse_date() reject impossible calendar dates (e.g. 2023-02-29, 2024-04-31) instead of silently returning a tuple describing a non-existent date. After parsing the string into a (year, month, day, hour, minute, second) tuple, it now validates the date portion by constructing a datetime.date object, which raises ValueError for invalid dates and is converted into the existing InvalidDate error. This tightens an edge case that previously pushed validation failures onto callers (via datetime(*parse_date(...))) or allowed time.mktime to silently normalize into a different month.
Changes:
- Validate the parsed year/month/day with
datetime.date(*result[:3])before returning, reusing the existingInvalidDateerror path. - Update the docstring to note that calendar validity is now checked.
- Add two tests covering rejected impossible dates and preserved leap-day/month-end/partial-date behavior.
| File | Description |
|---|---|
| humanfriendly/__init__.py | Adds calendar-date validation in parse_date() and documents the new InvalidDate condition. |
| humanfriendly/tests.py | Adds test_parse_date_invalid_calendar_dates and test_parse_date_calendar_boundaries covering rejection and boundary cases. |
Review effort: Balanced
parse_date('2023-02-29')andparse_date('2024-04-31 12:34:56')currently return tuples describing impossible calendar dates. A caller following the documenteddatetime(*parse_date(...))example then receives a separate ValueError, whiletime.mktimecan silently normalize those dates into a different month.Validate the parsed year/month/day with
datetime.datebefore returning the tuple, using the existingInvalidDateerror path for failures. Document that calendar validity is checked. The parsing formats, partial-date defaults and time-component handling are otherwise preserved. This intentionally rejects previously accepted impossible dates.Tests cover seven invalid calendar dates in both date-only and date/time forms, along with leap-year, month-end and partial-date controls.
Validation (Linux/WSL, CPython 3.12.3):
InvalidDate not raised; the existing date test and new calendar-boundary controls pass (1 failed, 2 passed).git diff --checkpasses.pipesdeprecation warning. Python 3.13 test collection is blocked by that existing import; this patch does not change CLI imports. Other Python/OS combinations were not validated.No overlapping issue or PR was found in the repository searches. Found through source inspection and prepared with OpenAI Codex assistance; no production incident or human manual review is claimed.