Skip to content

Issue 17774 - Usage - Local - Show data from midnight to midnight of selected dates for browser time zone (AI assisted)#19357

Merged
Takhoffman merged 2 commits into
openclaw:mainfrom
huntharo:issue-17774/usage-time-offsets
Feb 21, 2026
Merged

Issue 17774 - Usage - Local - Show data from midnight to midnight of selected dates for browser time zone (AI assisted)#19357
Takhoffman merged 2 commits into
openclaw:mainfrom
huntharo:issue-17774/usage-time-offsets

Conversation

@huntharo

@huntharo huntharo commented Feb 17, 2026

Copy link
Copy Markdown
Member

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: Usage tab fails to show data after midnight UTC in time zones that trail UTC date change
  • Why it matters: It can be difficult to detect that you are actually causing usage but that the dashboard just isn't showing it even when Local timezone is selected and current date is selected - You could be running up a bill and not realize it
  • What changed: Added time zone mode and offset fields to the usage request so the Local mode can actually select activity to for the local date time range rather than just the UTC time range for the selected date
  • What did NOT change (scope boundary): Backwards compatible - new request parameters are not required and their absence causes the existing behavior to be preserved - the UI will resend the request without the parameters if the service rejects the request with the new params

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

  • Local on Usage tab will now select midnight to midnight in the local time zone for the selected dates rather than UTC midnight to midnight on the selected dates
  • Most visible impact is that after 7 PM in NYC the Usage tab will continue to report data with todays date selecetd instead of becoming a snapshot of what happened on that date in UTC

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No (new params on Usage gateway websocket request - I don't think this is what is meant?)
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: N/A or Mac OS 26.2
  • Runtime/container: N/A or Node 22
  • Model/provider: N/A (non-model related)
  • Integration/channel (if any): N/A
  • Relevant config (redacted):

Steps

  1. Wait till after 7 PM NYC time (or 4 PM San Fran time)
  2. Have machine configured to NYC or San Fran time (both Gateway and Browser)
  3. Switch to a Model not used before
  4. Use the model
  5. Refresh Usage tab with Local selected and today's date selected (Today button should do this for you when Local is selected)

Expected

  • New model would show up in the list of models used today
  • Total model / token usage amounts would increase

Actual

  • Page is now static - will not change at all as it is looking only up till midnight UTC for the selected date and midnight UTC is already past

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

After - Modified UI + Modified Gateway - Changes to correct data for local date

image

After - Modified UI + Unmodified Gateway - Preserves current behavior / no errors / backwards compatible

image

After - Unmodified UI + Modified Gateway - Preserves current behavior / no errors / params not passed

image

Before - Only Today Selected with Local

Image

Before - Today + Tomorrow Selected with Local

Image

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios (manual in browser / starting stoping mix of gateways + UIs / examining websocket messages):
    • Modified UI + Unmodified Gateway - No errors, previous behavior
    • Unmodified UI + Modified Gateway - No errors, previous behavior
    • Modified UI + Modified Gateway
      • Local Selected - No errors, shows correct data for midnight to midnight local on selected date
      • UTC Selected - No errors, shows correct data for midnight to midnight UTC on selected date
  • Edge cases checked:
    • Covered in verified scenarios
  • What you did not verify:
    • I did not specifically verify that the IST (+5:30) offset works

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly:
  • Files/config to restore:
  • Known bad symptoms reviewers should watch for:

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

None

Greptile Summary

This PR fixes a real user-facing bug where the Usage tab would stop showing current-day data after midnight UTC for users in time zones that trail the UTC date change (e.g., NYC after 7 PM, San Francisco after 4 PM). The fix adds mode and utcOffset request parameters to the sessions.usage and usage.cost gateway endpoints, allowing the server to interpret date boundaries in the client's local timezone rather than always using UTC midnight.

Key changes:

  • Gateway (sessions.ts, usage.ts): New optional mode (utc / gateway / specific) and utcOffset fields on the SessionsUsageParamsSchema. Helper functions parseUtcOffsetToMinutes, resolveDateInterpretation, getTodayStartMs handle timezone-aware date math. Backward compatible — missing params default to UTC behavior.
  • UI (usage.ts): UsageState gains a usageTimeZone: "local" | "utc" field. loadUsage now calls buildDateInterpretationParams and spreads mode/utcOffset into both API calls. toErrorMessage improves error serialization.
  • Tests: Good coverage of gateway helpers and the UI controller with both happy-path and fallback scenarios.

One logic bug: the onTimeZoneChange handler updates state.usageTimeZone but does not call loadUsage, so the displayed data remains stale until the user manually refreshes. Since this PR makes the timezone selection functionally meaningful for the first time, a reload should be triggered on change.

One minor style issue: the utcOffset JSON Schema regex permits UTC+14:30, which passes validation but is silently rejected by parseUtcOffsetToMinutes and falls back to UTC mode without any error.

Confidence Score: 3/5

  • Safe to merge with one behavioral fix needed: timezone switching does not reload data.
  • The core logic — timezone-aware UTC offset math, backward compatibility, schema additions, and test coverage — is correct and well-implemented. The fix solves the stated problem. However, there is a logic gap: changing the timezone dropdown does not trigger a loadUsage call, so the UI will display stale data with the old timezone interpretation until the user manually refreshes. This directly undermines the intended UX of the fix. There is also a minor schema/parser inconsistency for UTC+14:30 (non-existent timezone), but that is a low-risk edge case. Score reflects that the fix works correctly once a load is triggered, but the missing automatic reload on timezone change is a real behavioral issue.
  • ui/src/ui/app-render-usage-tab.tsonTimeZoneChange should call loadUsage after updating state.

Last reviewed commit: 3944740

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

5 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Type.Union([Type.Literal("utc"), Type.Literal("gateway"), Type.Literal("specific")]),
),
/** UTC offset to use when mode is `specific` (for example, UTC-4 or UTC+5:30). */
utcOffset: Type.Optional(Type.String({ pattern: "^UTC[+-]\\d{1,2}(?::[0-5]\\d)?$" })),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Schema pattern is more permissive than the parser

The utcOffset pattern ^UTC[+-]\\d{1,2}(?::[0-5]\\d)?$ accepts UTC+14:30 (14 hours, 30 minutes), which passes schema validation for sessions.usage. However, parseUtcOffsetToMinutes in usage.ts explicitly rejects this value via if (hours === 14 && minutes !== 0) and silently falls back to UTC mode instead.

A client sending { mode: "specific", utcOffset: "UTC+14:30" } would receive no error but actually get UTC-scoped results. Tightening the regex to disallow :30 when hours equal 14 would surface this as a validation error rather than a silent fallback:

Suggested change
utcOffset: Type.Optional(Type.String({ pattern: "^UTC[+-]\\d{1,2}(?::[0-5]\\d)?$" })),
utcOffset: Type.Optional(Type.String({ pattern: "^UTC[+-](?:1[0-3]|\\d)(?::[0-5]\\d)?$|^UTC[+-]14(?::00)?$" })),

Alternatively, a simpler approach: since this is an edge case (UTC+14:30 is not a real timezone), this can be left as-is if silent fallback is acceptable.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/gateway/protocol/schema/sessions.ts
Line: 122:122

Comment:
**Schema pattern is more permissive than the parser**

The `utcOffset` pattern `^UTC[+-]\\d{1,2}(?::[0-5]\\d)?$` accepts `UTC+14:30` (14 hours, 30 minutes), which passes schema validation for `sessions.usage`. However, `parseUtcOffsetToMinutes` in `usage.ts` explicitly rejects this value via `if (hours === 14 && minutes !== 0)` and silently falls back to UTC mode instead.

A client sending `{ mode: "specific", utcOffset: "UTC+14:30" }` would receive no error but actually get UTC-scoped results. Tightening the regex to disallow `:30` when hours equal 14 would surface this as a validation error rather than a silent fallback:

```suggestion
    utcOffset: Type.Optional(Type.String({ pattern: "^UTC[+-](?:1[0-3]|\\d)(?::[0-5]\\d)?$|^UTC[+-]14(?::00)?$" })),
```

Alternatively, a simpler approach: since this is an edge case (UTC+14:30 is not a real timezone), this can be left as-is if silent fallback is acceptable.

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps

greptile-apps Bot commented Feb 17, 2026

Copy link
Copy Markdown
Contributor
Additional Comments (1)

ui/src/ui/app-render-usage-tab.ts
Timezone change does not reload data

onTimeZoneChange updates state.usageTimeZone but does not call loadUsage. This PR makes usageTimeZone actually affect the API request (choosing between mode: "specific" vs mode: "utc"), so switching the timezone dropdown will leave the displayed data stale — using the old timezone interpretation — until the user manually clicks Refresh or changes a date.

Since the entire point of this PR is to make the "Local" / "UTC" selection meaningful, switching between them should trigger a reload:

    onTimeZoneChange: (zone) => {
      state.usageTimeZone = zone;
      void loadUsage(state);
    },
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/ui/app-render-usage-tab.ts
Line: 74:76

Comment:
**Timezone change does not reload data**

`onTimeZoneChange` updates `state.usageTimeZone` but does not call `loadUsage`. This PR makes `usageTimeZone` actually affect the API request (choosing between `mode: "specific"` vs `mode: "utc"`), so switching the timezone dropdown will leave the displayed data stale — using the old timezone interpretation — until the user manually clicks Refresh or changes a date.

Since the entire point of this PR is to make the "Local" / "UTC" selection meaningful, switching between them should trigger a reload:

```suggestion
    onTimeZoneChange: (zone) => {
      state.usageTimeZone = zone;
      void loadUsage(state);
    },
```

How can I resolve this? If you propose a fix, please make it concise.

@huntharo huntharo changed the title Issue 17774 - Rolls royce usage dates Issue 17774 - Usage - Local - Show data from midnight to midnight of selected dates for browser time zone Feb 17, 2026
@huntharo

Copy link
Copy Markdown
Member Author

Additional Comments (1)
ui/src/ui/app-render-usage-tab.ts Timezone change does not reload data

onTimeZoneChange updates state.usageTimeZone but does not call loadUsage. This PR makes usageTimeZone actually affect the API request (choosing between mode: "specific" vs mode: "utc"), so switching the timezone dropdown will leave the displayed data stale — using the old timezone interpretation — until the user manually clicks Refresh or changes a date.

Since the entire point of this PR is to make the "Local" / "UTC" selection meaningful, switching between them should trigger a reload:

What no? That is not the entire point of this PR.

The point of this PR is to make the UI + gateway capable of selecting a full day in a local timezone, at all (it can't now).

The existing UI functionality of not loading anything until Refresh is clicked is a completely orthognal issue that can be changed or not changed.

@huntharo
huntharo force-pushed the issue-17774/usage-time-offsets branch 2 times, most recently from 1aa5c50 to cc47a45 Compare February 18, 2026 19:30
@huntharo huntharo changed the title Issue 17774 - Usage - Local - Show data from midnight to midnight of selected dates for browser time zone Issue 17774 - Usage - Local - Show data from midnight to midnight of selected dates for browser time zone (AI assisted) Feb 18, 2026
@openclaw-barnacle openclaw-barnacle Bot added the app: macos App: macos label Feb 18, 2026
@huntharo
huntharo force-pushed the issue-17774/usage-time-offsets branch 4 times, most recently from 1b609b7 to afc1068 Compare February 19, 2026 00:05
@Takhoffman Takhoffman self-assigned this Feb 21, 2026
@Takhoffman
Takhoffman force-pushed the issue-17774/usage-time-offsets branch from a672de2 to 61426f4 Compare February 21, 2026 02:06
@Takhoffman
Takhoffman merged commit 844d84a into openclaw:main Feb 21, 2026
21 of 24 checks passed
@Takhoffman

Copy link
Copy Markdown
Contributor

PR #19357 - Issue 17774 - Usage - Local - Show data from midnight to midnight of selected dates for browser time zone (AI assisted) (#19357)

Merged via squash.

  • Merge commit: 844d84a
  • Verified: pnpm install --frozen-lockfile, pnpm build, pnpm check, pnpm test:macmini (override approved by Tak for local baseline failures outside PR scope)
  • Changes made:
    M CHANGELOG.md
    M apps/macos/Sources/OpenClawProtocol/GatewayModels.swift
    M apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift
    M src/gateway/protocol/schema/sessions.ts
    M src/gateway/server-methods/usage.test.ts
    M src/gateway/server-methods/usage.ts
    M ui/src/ui/app-render-usage-tab.ts
    A ui/src/ui/controllers/usage.node.test.ts
    M ui/src/ui/controllers/usage.ts
  • Why these changes were made:
    Addressed stale usage data when timezone changes by triggering immediate reload in the usage tab, and preserved changelog coverage while rebasing onto latest main for merge safety.
  • Changelog: CHANGELOG.md updated=true required=true opt_out=false

Thanks @huntharo!

@huntharo
huntharo deleted the issue-17774/usage-time-offsets branch February 21, 2026 03:17
@huntharo

Copy link
Copy Markdown
Member Author

Thank you @Takhoffman !

mmyyfirstb pushed a commit to mmyyfirstb/openclaw that referenced this pull request Feb 21, 2026
…selected dates for browser time zone (AI assisted) (openclaw#19357) thanks @huntharo

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini (override approved by Tak for this run; local baseline failures outside PR scope)

Co-authored-by: huntharo <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
mreedr pushed a commit to mreedr/openclaw-custom that referenced this pull request Feb 24, 2026
…selected dates for browser time zone (AI assisted) (openclaw#19357) thanks @huntharo

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini (override approved by Tak for this run; local baseline failures outside PR scope)

Co-authored-by: huntharo <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…selected dates for browser time zone (AI assisted) (openclaw#19357) thanks @huntharo

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini (override approved by Tak for this run; local baseline failures outside PR scope)

Co-authored-by: huntharo <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…selected dates for browser time zone (AI assisted) (openclaw#19357) thanks @huntharo

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini (override approved by Tak for this run; local baseline failures outside PR scope)

Co-authored-by: huntharo <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…selected dates for browser time zone (AI assisted) (openclaw#19357) thanks @huntharo

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini (override approved by Tak for this run; local baseline failures outside PR scope)

Co-authored-by: huntharo <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: macos App: macos app: web-ui App: web-ui gateway Gateway runtime size: L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard date filter uses UTC instead of configured user timezone

2 participants