Skip to content

fix(cli): preserve explicit T00:00:00 in --until (#870)#872

Merged
microsasa merged 3 commits intomainfrom
fix/870-until-explicit-midnight-fc18960c8f7caa51
Apr 8, 2026
Merged

fix(cli): preserve explicit T00:00:00 in --until (#870)#872
microsasa merged 3 commits intomainfrom
fix/870-until-explicit-midnight-fc18960c8f7caa51

Conversation

@microsasa
Copy link
Copy Markdown
Owner

Closes #870

Problem

_normalize_until expanded any midnight datetime to end-of-day (23:59:59.999999), regardless of whether the user typed --until 2025-01-15 (date-only) or --until 2025-01-15T00:00:00 (explicit midnight). Because click.DateTime discards the original string format, the function could not distinguish the two cases.

A user who typed --until 2025-01-15T00:00:00 intending "strictly before midnight" would silently get all January 15 sessions included.

Solution

  • Introduced _ParsedDateArg frozen dataclass carrying value: datetime and has_explicit_time: bool.
  • Replaced click.DateTime for --until on both summary and cost commands with a custom _DateTimeOrDate(click.ParamType) that parses %Y-%m-%d as date-only (has_explicit_time=False) and %Y-%m-%dT%H:%M:%S as explicit time (has_explicit_time=True).
  • Updated _normalize_until to only expand to end-of-day when has_explicit_time is False.
  • --since parameters remain unchanged (using click.DateTime).

Tests Added

  • TestDateTimeOrDateParamType — unit tests for the custom Click param type (date-only, datetime, explicit midnight, invalid input, datetime passthrough).
  • TestNormalizeUntilParametrised — parametrised tests covering the 3 key cases: date-only expanded, explicit midnight not expanded, non-midnight unchanged.
  • TestIssue870ExplicitMidnight — CLI-level regression tests via CliRunner for both summary and cost commands, verifying boundary inclusion/exclusion and --since sanity check.
  • Updated existing TestNormalizeUntil, TestNormalizeUntilNonUtcTimezone, and TestValidateSinceUntil to use _ParsedDateArg.

All 1258 unit tests and 86 e2e tests pass. Coverage remains at ~99%.

Generated by Issue Implementer · ● 18.7M ·

Replace click.DateTime for --until with a custom _DateTimeOrDate
ParamType that distinguishes date-only from full-datetime inputs.
_normalize_until now only expands to end-of-day when the user
supplied a date without a time component (has_explicit_time=False).

An explicit --until 2025-01-15T00:00:00 is left as-is, giving
strict before-midnight semantics. --since is unaffected.

Tests cover:
- _DateTimeOrDate param type parsing (date-only, datetime, midnight, invalid)
- _normalize_until with _ParsedDateArg (parametrised 3 cases)
- CLI-level regression via CliRunner for summary and cost commands
- --since sanity check

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@microsasa microsasa added the aw Created by agentic workflow label Apr 8, 2026
Copilot AI review requested due to automatic review settings April 8, 2026 21:20
@microsasa microsasa enabled auto-merge April 8, 2026 21:20
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes the CLI --until handling so that an explicitly provided midnight timestamp (YYYY-MM-DDT00:00:00) is preserved (strict cutoff), while date-only inputs (YYYY-MM-DD) continue to expand to end-of-day for inclusive “whole day” behavior.

Changes:

  • Added a _ParsedDateArg carrier and a custom Click param type _DateTimeOrDate to distinguish date-only vs datetime input for --until.
  • Updated _normalize_until / _validate_since_until to only expand midnight when the user did not supply an explicit time.
  • Expanded unit + CLI regression tests to cover explicit-midnight boundary inclusion/exclusion for summary and cost.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/copilot_usage/cli.py Introduces _DateTimeOrDate + _ParsedDateArg and updates --until parsing/normalization semantics.
tests/copilot_usage/test_cli.py Updates existing tests and adds new unit/CLI regression coverage for issue #870 behavior.

- Derive _DateTimeOrDate._try_parse formats from shared _FORMAT_SPECS
  constant instead of hardcoding, creating a single source of truth
  with _DATE_FORMATS
- Reword --until help text on summary and cost commands to describe
  timestamp cutoff semantics accurately
- Fix docstring count mismatch (four → three) in
  TestNormalizeUntilParametrised

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

Commit pushed: b059418

Generated by Review Responder

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

- Replace standalone triple-quoted docstring on _FORMAT_SPECS with # comment (B018)
- Rename _DateTimeOrDate.name from 'datetime' to 'datetime-or-date'
- Fix --until help text on cost command to match inclusive semantics
- Unify --until help text wording between summary and cost commands

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

Commit pushed: 7b58171

Generated by Review Responder

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@microsasa microsasa added the aw-quality-gate-approved Quality gate approved the PR label Apr 8, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Quality Gate: APPROVED (medium-impact bug fix)

Evaluated across code quality and blast radius dimensions:

  • Code quality: Well-structured fix introducing _ParsedDateArg (frozen dataclass) and _DateTimeOrDate (Click ParamType) to distinguish date-only from datetime --until inputs. Follows all coding guidelines (strict typing, isinstance at I/O boundary only, Final constants, frozen dataclass with slots=True).
  • Tests: 233 lines of new/updated tests covering the custom param type, parametrized _normalize_until behavior, and CLI-level regression tests for both summary and cost commands. All meaningful — no no-ops.
  • Impact: Medium — focused fix to --until parsing in cli.py. No changes to data models, parsers, or external API contracts. --since is unaffected. All existing tests updated to use new type.
  • CI: All 10 checks passing.

Auto-approving for merge.

@microsasa microsasa merged commit 026381f into main Apr 8, 2026
10 checks passed
@microsasa microsasa deleted the fix/870-until-explicit-midnight-fc18960c8f7caa51 branch April 8, 2026 21:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

aw Created by agentic workflow aw-quality-gate-approved Quality gate approved the PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[aw][code health] --until silently overrides explicit T00:00:00 time component

2 participants