Skip to content

--since/--until accept invalid dates and silently return wrong results #1483

Closed

Description

@LeeYudok

What happened?

--since and --until are documented as YYYY-MM-DD or YYYYMMDD, but a value that is neither is not rejected. The bound is normalized with value.replace('-', "") and then compared as a plain string against the YYYYMMDD row keys, so an invalid bound either turns the filter into a no-op or drops every row. Exit code is 0 in all cases, so a script has no way to notice.

normalize_date_bound (rust/crates/ccusage-cli/src/types.rs:70) is the whole normalization:

pub fn normalize_date_bound(value: &str) -> String {
    value.replace('-', "")
}

and filter_and_sort_summaries (rust/crates/ccusage/src/summary.rs:277) compares the result as a string, so nothing checks that the bound is a real date.

This is the same failure shape as #1108, which fixed the dashed format but did not add validation.

Steps to reproduce

Local data spanning 2026-05-05 to 2026-07-24, 34 daily rows.

command rows returned expected
ccusage daily --since 2026-02-30 34 (all) error
ccusage daily --since 2026-13-01 0 error
ccusage daily --since abc 0 error
ccusage daily --since 2026/07/10 34 (all) error
ccusage daily --until 2026-02-30 0 error
ccusage daily --until 2026-13-01 34 (all) error
ccusage daily --until abc 34 (all) error

--until is the mirror of --since because the comparison is lexicographic. abc sorts after any 2026... string, 20260230 sorts before every row in range, and 2026/07/10 keeps its slashes, which sort before digits.

One more case: --since 2026-07-10T00:00:00Z normalizes to 20260710T00:00:00Z, which sorts after 20260710, so it silently drops 2026-07-10 itself and the report starts at 2026-07-11.

Expected behavior

An invalid bound should be rejected with a message naming the flag, and a non-zero exit.

A bound could be accepted only if it matches one of the two documented forms and is a real calendar date. Date::from_ymd (rust/crates/ccusage/src/date_utils.rs:81) already does the calendar check including leap years. Config-file bounds call the same function (rust/crates/ccusage/src/config.rs:527), so they would need the same check.

normalize_date_bound has no direct unit tests right now, so the cases above could be added there.

I would like to implement this myself if the approach sounds right.

Version

20.0.18, and also reproduced with a release build of main @ 31e084a.

Activity

  1. pullfrog commented on Jul 24, 2026

    @pullfrog
    Contributor
  2. github-actions commented on Jul 24, 2026

    @github-actions
    Contributor

    This issue was auto-closed. Issues from new contributors are auto-closed by default.

    Maintainers review auto-closed issues and reopen worthwhile ones. Issues that do not meet the quality bar in CONTRIBUTING.md may not be reopened or receive a reply.

    Keep the issue short, concrete, and written in your own voice.

    If a maintainer replies lgtmi, your future issues will stay open. If a maintainer replies lgtm, your future issues and PRs will stay open.

    See CONTRIBUTING.md.

  3. LeeYudok commented on Jul 27, 2026

    @LeeYudok
    ContributorAuthor

    Implementation is up at #1502. The PR gate auto-closed it since I am not in APPROVED_CONTRIBUTORS yet — the branch and diff are intact, so reopening it is enough if the approach looks right.

    Summary of what changed versus the approach in this issue: the crate split means ccusage-cli cannot reach IsoDate::from_ymd in ccusage-core, since ccusage-cli is dependency-free by design and sits on every adapter's critical path. The calendar check is implemented locally there instead. Config-file bounds are validated in ConfigContext::from_args and surface through the existing config_error channel, because apply_shared_options cannot fail.

    One judgment call worth your input: --since 2026-07-10T00:00:00Z is rejected rather than truncated to 20260710. It is not one of the documented formats and it was silently dropping that day, but I am happy to accept and truncate instead.

  4. mr-tiwari-ji commented on Aug 5, 2026

    @mr-tiwari-ji

    Hi @ryoppippi ,
    I am facing an issue while using the instances option, According to the documentation, the daily command supports the --instances (or -i) option to group usage by project. However, on ccusage v20.0.19, the CLI reports:
    Unknown option '--instances'
    Image
    Image
    The --instances option should be recognized and group daily usage by project instead of aggregating across all projects, as documented.

  5. ryoppippi commented on Aug 31, 2026

    @ryoppippi
    Member

    Historical audit: this discussion was auto-closed by the legacy contributor gate. That closure did not assess technical importance.

    Audit result: resolved. A later merged change or the current main implementation covers this request. This item is kept for history and does not need to be reopened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriage:resolvedResolved by a later change or current implementation.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions