Skip to content

Restore clipped day in Arrow.range() for plural frame names - #1354

Open
Str0k wants to merge 1 commit into
arrow-py:masterfrom
Str0k:fix/range-plural-frames-restore-day
Open

Str0k wants to merge 1 commit into
arrow-py:masterfrom
Str0k:fix/range-plural-frames-restore-day

Conversation

@Str0k

@Str0k Str0k commented Sep 14, 2026

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.
  • 🛠️ All tests pass when run locally (run tox or make test to find out!).
  • 🧹 All linting checks pass when run locally (run tox -e lint or make lint to find out!).
  • 📚 Updated documentation for changed code.
  • ⏩ Code is up-to-date with the master branch.

Description of Changes

Arrow.range() accepts plural frame names ("months", "quarters", "years") through _get_frames(), and they iterate over the same steps as the singular names. But the end-of-month "restore the clipped day" logic compares the raw frame argument against ["month", "quarter", "year"], so it never fires for the plural spellings. After passing through a shorter month, the day stays clipped for the rest of the range:

>>> [a.format("YYYY-MM-DD") for a in arrow.Arrow.range("month", datetime(2015, 1, 31), limit=4)]
['2015-01-31', '2015-02-28', '2015-03-31', '2015-04-30']
>>> [a.format("YYYY-MM-DD") for a in arrow.Arrow.range("months", datetime(2015, 1, 31), limit=4)]
['2015-01-31', '2015-02-28', '2015-03-28', '2015-04-28']   # before this change

span_range() forwards frame to range() unchanged, so it was affected in the same way.

The fix keeps the normalized frame name that _get_frames() already returns and uses it for the comparison, so "month"/"months", "quarter"/"quarters" and "year"/"years" behave identically. The existing singular-name regression tests (e.g. #842) are unchanged.

Tests

Added TestArrowRange.test_range_plural_frames_restore_clipped_day, parametrized over "months", "quarters" and "years" using the same dates as the existing singular-name tests. All three cases fail on master and pass with this change.

Locally on CPython 3.12: pytest tests → 1903 passed, 2 skipped. black --check, flake8 and isort --check-only are clean on the changed files. mypy arrow/arrow.py reports 3 errors in humanize() (lines ~1268–1296) that are identical with and without this change, so they come from my newer mypy version rather than from this PR. I did not run the full tox matrix, only the pytest suite on 3.12 and the linters above.

No documentation change: the docstring already lists these frames as supported, and this makes the plural forms behave as documented.


This change was prepared with AI assistance (Claude Code). I reproduced the bug on master, reviewed the diff and ran the tests and linters described above.

🤖 Generated with Claude Code

Arrow.range() accepts "months", "quarters" and "years" through
_get_frames(), but the end-of-month day-restore check compared the raw
frame argument against the singular names only. After a shorter month
the day therefore stayed clipped for the rest of the range, and
span_range() inherited the same behaviour.

Use the normalized frame name returned by _get_frames() for the check,
and add a parametrized regression test for the plural spellings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 14, 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 (64ff518).

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #1354   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           10        10           
  Lines         2315      2315           
  Branches       358       358           
=========================================
  Hits          2315      2315           

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

This branch has not been deployed

No deployments
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