Skip to content

Reject day of year 366 in a non-leap year instead of rolling over#1329

Open
Sreekant13 wants to merge 1 commit into
arrow-py:masterfrom
Sreekant13:fix/reject-day-366-non-leap
Open

Reject day of year 366 in a non-leap year instead of rolling over#1329
Sreekant13 wants to merge 1 commit into
arrow-py:masterfrom
Sreekant13:fix/reject-day-366-non-leap

Conversation

@Sreekant13

Copy link
Copy Markdown

Pull Request Checklist

Thank you for taking the time to improve Arrow! Before submitting your pull request, please check all appropriate boxes:

  • 🧪 Added tests for changed code. (Updated the existing test_YYYY_DDDD assertion; see below.)
  • 🛠️ All tests pass when run locally. (The parser test suite passes; I could not run the full tox matrix locally.)
  • 🧹 All linting checks pass when run locally. (Change is three source lines plus one test assertion; I did not run tox -e lint locally.)
  • 📚 Updated documentation for changed code. (N/A: no user-facing docs change.)
  • ⏩ Code is up-to-date with the master branch.

Description of Changes

The DDD/DDDD tokens and parse_iso validate the day of year with datetime.strptime("%Y-%j"), which accepts day 366 in a non-leap year and rolls the result over into January 1 of the following year rather than rejecting it. That is inconsistent with day 367 and above (which are rejected), and surprising because a "day of year" input returns a date in a different year than the one parsed.

For example, arrow.get("2023-366", "YYYY-DDD") currently returns 2024-01-01, while arrow.get("2023-367", ...) and arrow.get("2023-456", ...) are rejected with "The provided day of year N is invalid".

This detects the rollover and raises ParserError, matching the existing out-of-range handling: after strptime, if the resulting year differs from the parsed year, the day of year is out of range for that year. Leap years are unaffected, so arrow.get("2024-366", "YYYY-DDD") still returns 2024-12-31.

Note this is a small behavior change. test_YYYY_DDDD previously asserted parse_iso("2017-366") == datetime(2018, 1, 1) with a comment describing the rollover as expected; that assertion is updated to expect a ParserError. The parser test suite passes.

The DDD/DDDD tokens and parse_iso validate the day of year with
datetime.strptime("%Y-%j"), which accepts day 366 in a non-leap year and
rolls the result over into January 1 of the following year rather than
rejecting it. That is inconsistent with day 367 and above (rejected), and
surprising because a "day of year" input returns a date in a different
year. Detect the rollover and raise ParserError, matching the existing
out-of-range handling.
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (2224255) to head (0ae2607).

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #1329   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           10        10           
  Lines         2315      2317    +2     
  Branches       358       359    +1     
=========================================
+ Hits          2315      2317    +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

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.

1 participant