mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
fix(spend): convert string dates to tz-aware UTC datetimes in _get_spend_report_for_time_range
This helper takes start_date/end_date as plain strings and passed them straight to query_raw. Prisma forwards untyped text to Postgres, which parses `'2026-04-10'::timestamptz` using the session timezone because there's no +00:00 offset to respect. Under a non-UTC session this shifts the resolved instant by the session offset, and the AT TIME ZONE 'UTC' wrap introduced in the previous commit then strips it to a plain timestamp that's still offset by the same amount — producing the exact 4h drift that wrap was meant to prevent. Normalize the strings to datetime(..., tzinfo=timezone.utc) at the top of the function so Prisma serializes them with the explicit +00:00 suffix, which makes the ::timestamptz cast session-TZ-independent. Also replaces the $1::date comparison in the team_alias query with the same ::timestamptz AT TIME ZONE 'UTC' pattern used by every other site in this PR, so both queries share one consistent shape. Verified live on a real Postgres under session TZ America/New_York: the function now returns exactly the April 10 UTC demo rows ($4.20 / 10 rows) whereas the previous shape returned 13 rows (2 correct April 10 rows dropped, 5 rows from April 11 early-morning wrongly shifted in).
This commit is contained in:
parent
c7934c460d
commit
423677f19e
1 changed files with 16 additions and 3 deletions
|
|
@ -1456,6 +1456,16 @@ async def _get_spend_report_for_time_range(
|
|||
)
|
||||
return None
|
||||
|
||||
# Normalize string inputs to tz-aware UTC datetimes so Prisma serializes
|
||||
# them with an explicit +00:00 suffix. Raw strings get bound as untyped
|
||||
# text, which forces Postgres to parse `::timestamptz` using the DB
|
||||
# session timezone and drifts the window by the offset even with the
|
||||
# AT TIME ZONE 'UTC' wrap below.
|
||||
start_date_obj = datetime.strptime(start_date, "%Y-%m-%d").replace(
|
||||
tzinfo=timezone.utc
|
||||
)
|
||||
end_date_obj = datetime.strptime(end_date, "%Y-%m-%d").replace(tzinfo=timezone.utc)
|
||||
|
||||
try:
|
||||
sql_query = """
|
||||
SELECT
|
||||
|
|
@ -1466,13 +1476,16 @@ async def _get_spend_report_for_time_range(
|
|||
LEFT JOIN
|
||||
"LiteLLM_TeamTable" t ON s.team_id = t.team_id
|
||||
WHERE
|
||||
s."startTime" >= $1::date AND s."startTime" < ($2::date + INTERVAL '1 day')
|
||||
s."startTime" >= ($1::timestamptz AT TIME ZONE 'UTC')
|
||||
AND s."startTime" < (($2::timestamptz + INTERVAL '1 day') AT TIME ZONE 'UTC')
|
||||
GROUP BY
|
||||
t.team_alias
|
||||
ORDER BY
|
||||
total_spend DESC;
|
||||
"""
|
||||
response = await prisma_client.db.query_raw(sql_query, start_date, end_date)
|
||||
response = await prisma_client.db.query_raw(
|
||||
sql_query, start_date_obj, end_date_obj
|
||||
)
|
||||
|
||||
# get spend per tag for today
|
||||
sql_query = """
|
||||
|
|
@ -1487,7 +1500,7 @@ async def _get_spend_report_for_time_range(
|
|||
"""
|
||||
|
||||
spend_per_tag = await prisma_client.db.query_raw(
|
||||
sql_query, start_date, end_date
|
||||
sql_query, start_date_obj, end_date_obj
|
||||
)
|
||||
|
||||
return response, spend_per_tag
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue