mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-29 06:33:28 +00:00
fix(budget): correct multi-day rollover in standardized reset-time handlers
_handle_hour_reset, _handle_minute_reset and _handle_second_reset reduced the overflowing next_hour with % 24 but always advanced the date by a single timedelta(days=1). Any duration spanning >= 48h (e.g. 48h, 72h, 3000m, 180000s) therefore reset up to days too early -- 48h from 10:00 landed the reset only 14h out, and 72h advanced a single day instead of three. Capture days_ahead = next_hour // 24 before the modulo so the full whole-day overflow is applied. Fixes #17993. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N6RtoHuxrDqTUo9Mw9h4Cv
This commit is contained in:
parent
bd44c9e305
commit
c602c9a94a
2 changed files with 31 additions and 3 deletions
|
|
@ -236,8 +236,9 @@ def _handle_hour_reset(current_time: datetime, base_midnight: datetime, value: i
|
|||
|
||||
# Handle overnight case
|
||||
if next_hour >= 24:
|
||||
days_ahead = next_hour // 24
|
||||
next_hour = next_hour % 24
|
||||
next_day = base_midnight + timedelta(days=1)
|
||||
next_day = base_midnight + timedelta(days=days_ahead)
|
||||
return next_day.replace(hour=next_hour)
|
||||
|
||||
return current_time.replace(hour=next_hour, minute=0, second=0, microsecond=0)
|
||||
|
|
@ -270,8 +271,9 @@ def _handle_minute_reset(current_time: datetime, base_midnight: datetime, value:
|
|||
|
||||
# Handle overnight case
|
||||
if next_hour >= 24:
|
||||
days_ahead = next_hour // 24
|
||||
next_hour = next_hour % 24
|
||||
next_day = base_midnight + timedelta(days=1)
|
||||
next_day = base_midnight + timedelta(days=days_ahead)
|
||||
return next_day.replace(hour=next_hour, minute=next_minute, second=0, microsecond=0)
|
||||
|
||||
return current_time.replace(hour=next_hour, minute=next_minute, second=0, microsecond=0)
|
||||
|
|
@ -309,8 +311,9 @@ def _handle_second_reset(current_time: datetime, base_midnight: datetime, value:
|
|||
|
||||
# Handle overnight case
|
||||
if next_hour >= 24:
|
||||
days_ahead = next_hour // 24
|
||||
next_hour = next_hour % 24
|
||||
next_day = base_midnight + timedelta(days=1)
|
||||
next_day = base_midnight + timedelta(days=days_ahead)
|
||||
return next_day.replace(hour=next_hour, minute=next_minute, second=next_second, microsecond=0)
|
||||
|
||||
return current_time.replace(hour=next_hour, minute=next_minute, second=next_second, microsecond=0)
|
||||
|
|
|
|||
|
|
@ -71,6 +71,31 @@ class TestStandardizedResetTime(unittest.TestCase):
|
|||
second_result = get_next_standardized_reset_time("15s", base_time, "UTC")
|
||||
self.assertEqual(second_result, second_expected)
|
||||
|
||||
def test_multi_day_rollover_resets(self):
|
||||
"""Durations spanning more than 24h must advance the full number of days."""
|
||||
# Base time: 2023-05-15 10:00 UTC
|
||||
base_time = datetime(2023, 5, 15, 10, 0, 0, tzinfo=timezone.utc)
|
||||
|
||||
# 48h aligns to midnight + 48h; first boundary after 10:00 is the 17th.
|
||||
self.assertEqual(
|
||||
get_next_standardized_reset_time("48h", base_time, "UTC"),
|
||||
datetime(2023, 5, 17, 0, 0, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
# 72h -> the 18th (previously advanced only a single day).
|
||||
self.assertEqual(
|
||||
get_next_standardized_reset_time("72h", base_time, "UTC"),
|
||||
datetime(2023, 5, 18, 0, 0, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
# 3000m == 50h and 180000s == 50h -> 10:00 + 50h == the 17th at 12:00.
|
||||
self.assertEqual(
|
||||
get_next_standardized_reset_time("3000m", base_time, "UTC"),
|
||||
datetime(2023, 5, 17, 12, 0, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
self.assertEqual(
|
||||
get_next_standardized_reset_time("180000s", base_time, "UTC"),
|
||||
datetime(2023, 5, 17, 12, 0, 0, tzinfo=timezone.utc),
|
||||
)
|
||||
|
||||
def test_timezone_handling(self):
|
||||
"""Test timezone handling with different regions"""
|
||||
# Base time: 2023-05-15 22:30:00 UTC (late in UTC day)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue