Skip to content

feat: add --from/--to date-range filtering for daily and monthly views - #224

Open
TobiWo wants to merge 4 commits into
Maciek-roboblog:mainfrom
TobiWo:feature/add-range-flags-for-view
Open

feat: add --from/--to date-range filtering for daily and monthly views#224
TobiWo wants to merge 4 commits into
Maciek-roboblog:mainfrom
TobiWo:feature/add-range-flags-for-view

Conversation

@TobiWo

@TobiWo TobiWo commented Jun 30, 2026

Copy link
Copy Markdown

Summary

Adds --from/--to to restrict the daily and monthly tables to an inclusive date range.

Format follows the view: daily takes YYYY-MM-DD, monthly takes YYYY-MM. Either bound works alone. The flags only apply to those two views — using them elsewhere is a validation error.

Most of the plumbing already existed. UsageAggregator accepts start_date/end_date and filters on the entry timestamp; the public aggregate() just never passed them. So this connects the flags to that filter instead of writing new aggregation. The totals row and period header follow automatically, since both come from the rows the aggregator returns.

One thing reviewers should know: these views read ~/.claude/projects/, which Claude Code prunes after cleanupPeriodDays (default 30). A range older than that returns no rows, not an error. The README explains how to raise the retention for longer monthly history.

Changes: the validated --from/--to fields on Settings, a _range_bounds() helper that builds timezone-aware inclusive bound (month-end via calendar.monthrange), tests for both views including boundary inclusivity and the error cases, and the README entries.

Closes #223

Summary by CodeRabbit

  • New Features
    • Added optional --from / --to date-range filters for daily and monthly table views (aliases supported).
    • Filtering is inclusive and applied during aggregation; supports one-sided ranges.
  • Bug Fixes
    • Enforces correct ISO formats per view, validates calendar dates, and rejects invalid/ordered ranges and unsupported views.
    • Bounds are interpreted using UTC-based daily keys even when display timezone is non-UTC; date-range replay now respects saved view vs explicitly provided view.
  • Documentation
    • Updated README with a “Filtering daily/monthly views by date range” section, examples, and retention notes.
  • Tests
    • Added coverage for inclusive bounds, edge cases (including leap years), and timezone/key behavior.

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b9096fd8-856a-4e77-9dce-d2ea2e63e31c

📥 Commits

Reviewing files that changed from the base of the PR and between 9e3a6f4 and 994aaa6.

📒 Files selected for processing (2)
  • src/claude_monitor/core/settings.py
  • src/tests/test_settings.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/tests/test_settings.py
  • src/claude_monitor/core/settings.py

📝 Walkthrough

Walkthrough

Adds --from and --to filters for daily and monthly table views. The settings layer validates and exports the new fields, the aggregator applies inclusive bounds, the CLI forwards the values, and the README and tests reflect the new behavior.

Changes

Date Range Filtering

Layer / File(s) Summary
Settings fields and validation
src/claude_monitor/core/settings.py, src/tests/test_settings.py
Adds date_from/date_to fields with aliases, validates view-specific formats and ordering, preserves aliased CLI values, and exports them to namespaces.
UsageAggregator bounds logic
src/claude_monitor/data/aggregator.py, src/tests/test_aggregator.py
Adds date-range parameters, computes inclusive bounds, and applies them to daily/monthly aggregation with coverage for monthly limits, one-sided ranges, and timezone behavior.
CLI wiring and docs
src/claude_monitor/cli/main.py, README.md
Passes date_from and date_to into UsageAggregator and documents the new flags, formats, and retention notes.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI args
  participant Settings as Settings
  participant Aggregator as UsageAggregator
  participant TableView as daily/monthly table view
  CLI->>Settings: parse --from/--to
  Settings->>Settings: validate range for view
  CLI->>Aggregator: pass date_from/date_to
  Aggregator->>TableView: aggregate with bounds
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding from/to date-range filtering for daily and monthly views.
Linked Issues check ✅ Passed The PR adds inclusive --from/--to filtering for daily and monthly views, supports one-sided ranges, and enforces the required date formats.
Out of Scope Changes check ✅ Passed The changes stay focused on the date-range feature, its validation, tests, and documentation, with no clear unrelated additions.
Docstring Coverage ✅ Passed Docstring coverage is 96.97% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/tests/test_aggregator.py (1)

403-516: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider adding non-UTC timezone coverage for _range_bounds().

Every new test pins timezone="UTC", so the timezone-aware bound construction in _range_bounds() (which builds boundaries in the display timezone via make_aware) is never exercised against entries in a different zone. A test with e.g. timezone="America/New_York" would confirm that a local-day boundary correctly includes/excludes UTC-stamped entries near midnight.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tests/test_aggregator.py` around lines 403 - 516, Add a test that
exercises UsageAggregator._range_bounds() with a non-UTC timezone, since the
current cases only use timezone="UTC" and do not verify make_aware-boundary
behavior in a local zone. Use the existing UsageAggregator, _range_bounds, and
aggregate_daily/aggregate_monthly patterns to assert that a timezone like
America/New_York correctly includes or excludes UTC-stamped UsageEntry values
near midnight based on the local-day boundary.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/claude_monitor/core/settings.py`:
- Around line 277-292: The last-used replay in load_with_last_used() is
comparing raw CLI flag names to cls.model_fields, so the aliased --from/--to
inputs are not normalized to date_from/date_to and can be overwritten by stale
saved values. Update the CLI field collection logic in load_with_last_used()
(and any helper it uses) to map aliases to their model field names before
deciding which settings were provided, using the date_from/date_to fields and
their from/to aliases as the reference points. Ensure explicit CLI range values
always take precedence over previously saved settings during replay.
- Around line 495-510: The date validation in the settings logic still accepts
non-canonical inputs and compares raw strings, so update the validation in the
code around the date parsing loop to parse each of `self.date_from` and
`self.date_to` once, require that formatting back with `strftime(...)` matches
the original value, and then use the parsed date objects for the `self.date_from
> self.date_to` check instead of comparing the original strings.

In `@src/claude_monitor/data/aggregator.py`:
- Around line 342-393: The `_range_bounds()` filtering logic in `Aggregator` is
using calendar start/end datetimes that don’t match how period keys are
generated, so boundary entries can be mis-bucketed or dropped. Update the range
filtering to follow the same semantics as the period-key logic used later in
aggregation (including `reset_hour` and timezone-aware daily/monthly keying), or
filter directly against the computed period keys in the aggregation flow. Make
sure the fix is applied consistently in `_range_bounds()` and the surrounding
aggregation path so the bounds and keys stay aligned.

---

Nitpick comments:
In `@src/tests/test_aggregator.py`:
- Around line 403-516: Add a test that exercises UsageAggregator._range_bounds()
with a non-UTC timezone, since the current cases only use timezone="UTC" and do
not verify make_aware-boundary behavior in a local zone. Use the existing
UsageAggregator, _range_bounds, and aggregate_daily/aggregate_monthly patterns
to assert that a timezone like America/New_York correctly includes or excludes
UTC-stamped UsageEntry values near midnight based on the local-day boundary.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a2a003fc-334e-47b3-a443-bfb1fd2232d5

📥 Commits

Reviewing files that changed from the base of the PR and between c59a83b and 6482981.

📒 Files selected for processing (6)
  • README.md
  • src/claude_monitor/cli/main.py
  • src/claude_monitor/core/settings.py
  • src/claude_monitor/data/aggregator.py
  • src/tests/test_aggregator.py
  • src/tests/test_settings.py

Comment thread src/claude_monitor/core/settings.py
Comment thread src/claude_monitor/core/settings.py Outdated
Comment thread src/claude_monitor/data/aggregator.py
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/claude_monitor/core/settings.py (1)

495-523: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Replay saved view before date-range validation. load_with_last_used() applies persisted values after the mode="after" validator runs, so --from/--to are still checked against the default realtime view and fail unless --view daily|monthly is repeated on the same invocation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/claude_monitor/core/settings.py` around lines 495 - 523, The date-range
validation in settings is running before the persisted view is restored, so
`--from` and `--to` are being validated against the default `realtime` mode
instead of the saved `view`. Update the `load_with_last_used()` flow and the
`mode="after"` validator in `src/claude_monitor/core/settings.py` so the
replayed `view` is applied before date validation, ensuring the
`date_pattern`/`expected` logic in the date-range check uses the effective view.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/claude_monitor/core/settings.py`:
- Around line 495-523: The date-range validation in settings is running before
the persisted view is restored, so `--from` and `--to` are being validated
against the default `realtime` mode instead of the saved `view`. Update the
`load_with_last_used()` flow and the `mode="after"` validator in
`src/claude_monitor/core/settings.py` so the replayed `view` is applied before
date validation, ensuring the `date_pattern`/`expected` logic in the date-range
check uses the effective view.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a7a44d14-ca7b-45fa-827d-3914c6669490

📥 Commits

Reviewing files that changed from the base of the PR and between 6482981 and a74f053.

📒 Files selected for processing (4)
  • src/claude_monitor/core/settings.py
  • src/claude_monitor/data/aggregator.py
  • src/tests/test_aggregator.py
  • src/tests/test_settings.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/claude_monitor/data/aggregator.py
  • src/tests/test_aggregator.py
  • src/tests/test_settings.py

@TobiWo
TobiWo force-pushed the feature/add-range-flags-for-view branch from 7c9f70b to 9e3a6f4 Compare July 1, 2026 10:27
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@TobiWo
TobiWo force-pushed the feature/add-range-flags-for-view branch from 9e3a6f4 to 994aaa6 Compare July 1, 2026 10:31
@TobiWo

TobiWo commented Jul 1, 2026

Copy link
Copy Markdown
Author

@Maciek-roboblog All comments raised by coderabbit have been adressed.

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.

Add --from/--to to daily and monthly view for more fine granular filtering

1 participant