fix(ui): adjust daily spend date filtering for user timezone#20472
Merged
yuneng-jiang merged 1 commit intoBerriAI:mainfrom Feb 5, 2026
Merged
fix(ui): adjust daily spend date filtering for user timezone#20472yuneng-jiang merged 1 commit intoBerriAI:mainfrom
yuneng-jiang merged 1 commit intoBerriAI:mainfrom
Conversation
The daily spend tables store dates in UTC, but the UI sends dates in the user's local timezone. This causes a mismatch where records from the user's evening (stored as the next UTC day) don't appear when filtering by "today". Changes: - Add `_adjust_dates_for_timezone()` helper to expand date range based on timezone offset - Add `timezone` query parameter to `/user/daily/activity` and `/user/daily/activity/aggregated` endpoints - Frontend sends `timezone` using `Date.getTimezoneOffset()` For users west of UTC (e.g., PST), end_date is extended by 1 day. For users east of UTC (e.g., IST), start_date is extended by 1 day earlier. This ensures all records within the user's local date range are captured.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Greptile OverviewGreptile SummaryFixes timezone mismatch between frontend date selection and backend UTC date filtering by expanding query date ranges based on user's timezone offset.
The implementation is straightforward and solves the stated problem. No new database objects are created in the request path, satisfying the performance guidelines. Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| litellm/proxy/management_endpoints/common_daily_activity.py | Added _adjust_dates_for_timezone() helper function to expand date ranges based on timezone offset, ensuring UTC database queries capture all records within user's local date range |
| litellm/proxy/management_endpoints/internal_user_endpoints.py | Added optional timezone query parameter to daily activity endpoints and passed through to common activity functions |
| ui/litellm-dashboard/src/components/networking.tsx | Added timezone offset parameter using Date.getTimezoneOffset() to daily activity API calls, but offset is calculated at request time which may not match the date selection time |
Sequence Diagram
sequenceDiagram
participant UI as Frontend (networking.tsx)
participant API as API Endpoint (internal_user_endpoints.py)
participant Helper as _adjust_dates_for_timezone()
participant Query as _build_where_conditions()
participant DB as Database (UTC dates)
UI->>UI: User selects date range (local timezone)
UI->>UI: formatDate() - Convert to YYYY-MM-DD
UI->>UI: getTimezoneOffset() - Get timezone offset in minutes
UI->>API: GET /user/daily/activity?start_date=2026-02-04&end_date=2026-02-04&timezone=480
API->>Helper: _adjust_dates_for_timezone(start_date, end_date, 480)
alt timezone > 0 (West of UTC, e.g. PST)
Helper->>Helper: end_date += 1 day
Note over Helper: Captures evening records<br/>stored in next UTC day
else timezone < 0 (East of UTC, e.g. IST)
Helper->>Helper: start_date -= 1 day
Note over Helper: Captures morning records<br/>stored in previous UTC day
else timezone == 0 or None
Helper->>Helper: No adjustment
end
Helper-->>API: Return adjusted_start_date, adjusted_end_date
API->>Query: _build_where_conditions() with adjusted dates
Query->>DB: SELECT * WHERE date >= adjusted_start AND date <= adjusted_end
DB-->>Query: Return matching UTC records
Query-->>API: Aggregated results
API-->>UI: SpendAnalyticsPaginatedResponse
Comment on lines
+1920
to
+1924
| timezone: Optional[int] = fastapi.Query( | ||
| default=None, | ||
| description="Timezone offset in minutes from UTC (e.g., 480 for PST). " | ||
| "Matches JavaScript's Date.getTimezoneOffset() convention.", | ||
| ), |
Contributor
There was a problem hiding this comment.
No validation bounds on timezone parameter - valid timezones range from -720 to +840 minutes
Suggested change
| timezone: Optional[int] = fastapi.Query( | |
| default=None, | |
| description="Timezone offset in minutes from UTC (e.g., 480 for PST). " | |
| "Matches JavaScript's Date.getTimezoneOffset() convention.", | |
| ), | |
| timezone: Optional[int] = fastapi.Query( | |
| default=None, | |
| ge=-720, | |
| le=840, | |
| description="Timezone offset in minutes from UTC (e.g., 480 for PST). " | |
| "Matches JavaScript's Date.getTimezoneOffset() convention.", | |
| ), |
Prompt To Fix With AI
This is a comment left during a code review.
Path: litellm/proxy/management_endpoints/internal_user_endpoints.py
Line: 1920:1924
Comment:
No validation bounds on `timezone` parameter - valid timezones range from -720 to +840 minutes
```suggestion
timezone: Optional[int] = fastapi.Query(
default=None,
ge=-720,
le=840,
description="Timezone offset in minutes from UTC (e.g., 480 for PST). "
"Matches JavaScript's Date.getTimezoneOffset() convention.",
),
```
How can I resolve this? If you propose a fix, please make it concise.
Comment on lines
+2011
to
+2015
| timezone: Optional[int] = fastapi.Query( | ||
| default=None, | ||
| description="Timezone offset in minutes from UTC (e.g., 480 for PST). " | ||
| "Matches JavaScript's Date.getTimezoneOffset() convention.", | ||
| ), |
Contributor
There was a problem hiding this comment.
No validation bounds on timezone parameter
Suggested change
| timezone: Optional[int] = fastapi.Query( | |
| default=None, | |
| description="Timezone offset in minutes from UTC (e.g., 480 for PST). " | |
| "Matches JavaScript's Date.getTimezoneOffset() convention.", | |
| ), | |
| timezone: Optional[int] = fastapi.Query( | |
| default=None, | |
| ge=-720, | |
| le=840, | |
| description="Timezone offset in minutes from UTC (e.g., 480 for PST). " | |
| "Matches JavaScript's Date.getTimezoneOffset() convention.", | |
| ), |
Prompt To Fix With AI
This is a comment left during a code review.
Path: litellm/proxy/management_endpoints/internal_user_endpoints.py
Line: 2011:2015
Comment:
No validation bounds on `timezone` parameter
```suggestion
timezone: Optional[int] = fastapi.Query(
default=None,
ge=-720,
le=840,
description="Timezone offset in minutes from UTC (e.g., 480 for PST). "
"Matches JavaScript's Date.getTimezoneOffset() convention.",
),
```
How can I resolve this? If you propose a fix, please make it concise.
Collaborator
|
lgtm |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The daily spend tables store dates in UTC, but the UI sends dates in the user's local timezone. This causes a mismatch where records from the user's evening (stored as the next UTC day) don't appear when filtering by "today".
Changes
_adjust_dates_for_timezone()helper to expand date range based on timezone offsettimezonequery parameter to/user/daily/activityand/user/daily/activity/aggregatedendpointstimezoneusingDate.getTimezoneOffset()How it works
end_dateis extended by 1 daystart_dateis extended by 1 day earlierExample
User in PST selects Feb 4:
start_date=2026-02-04&end_date=2026-02-04&timezone=480date >= '2026-02-04' AND date <= '2026-02-05'