Replace deprecated datetime.utcnow with shared naive-UTC helper

All 29 call sites now use app.timeutil.utcnow(), which returns naive
UTC via the non-deprecated API. Semantics are unchanged on purpose:
every datetime column is TIMESTAMP WITHOUT TIME ZONE, so going aware
here would poison naive/aware comparisons. The TIMESTAMPTZ migration
(Phase 2) now has a single place to change. (BE-01)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Carlos Escalante
2026-06-09 19:46:54 -06:00
parent 0a4c3e9436
commit 996bd437a1
9 changed files with 52 additions and 29 deletions

View File

@@ -8,6 +8,7 @@ from sqlalchemy import case
from sqlmodel import Session, col, select
from app.config import settings
from app.timeutil import utcnow
from app.db import engine
from app.models.models import ExchangeRate
@@ -136,7 +137,7 @@ def _fetch_rate_from_apis() -> tuple[float, float] | None:
def _remember(rate: ExchangeRate) -> ExchangeRate:
"""Store rate in both TTL cache and permanent last-known holder."""
global _last_known
_cache["current"] = (rate, datetime.utcnow())
_cache["current"] = (rate, utcnow())
_last_known = rate
return rate
@@ -147,11 +148,11 @@ def get_current_rate(session: Session) -> ExchangeRate | None:
# 1. Fresh memory cache (< 1 hour)
cached = _cache.get("current")
if cached and datetime.utcnow() - cached[1] < CACHE_TTL:
if cached and utcnow() - cached[1] < CACHE_TTL:
return cached[0]
# 2. Fresh DB rate (< 1 hour)
one_hour_ago = datetime.utcnow() - CACHE_TTL
one_hour_ago = utcnow() - CACHE_TTL
db_rate = session.exec(
select(ExchangeRate)
.where(ExchangeRate.fetched_at > one_hour_ago)
@@ -164,7 +165,7 @@ def get_current_rate(session: Session) -> ExchangeRate | None:
result = _fetch_rate_from_apis()
if result is not None:
buy, sell = result
rate = ExchangeRate(date=datetime.utcnow(), buy_rate=buy, sell_rate=sell)
rate = ExchangeRate(date=utcnow(), buy_rate=buy, sell_rate=sell)
session.add(rate)
session.commit()
session.refresh(rate)
@@ -230,7 +231,7 @@ def get_crc_rate(code: str) -> float | None:
return 1.0
cached = _xcrc_cache.get(code)
if cached and datetime.utcnow() - cached[1] < CACHE_TTL:
if cached and utcnow() - cached[1] < CACHE_TTL:
return cached[0]
if code in _COINGECKO_IDS:
@@ -239,7 +240,7 @@ def get_crc_rate(code: str) -> float | None:
rate = _fetch_fiat_crc_mid(code)
if rate is not None:
_xcrc_cache[code] = (rate, datetime.utcnow())
_xcrc_cache[code] = (rate, utcnow())
_last_known_xcrc[code] = rate
return rate
@@ -293,7 +294,7 @@ def _refresh_usd_rate() -> bool:
return False
buy, sell = fetched
with Session(engine) as session:
rate = ExchangeRate(date=datetime.utcnow(), buy_rate=buy, sell_rate=sell)
rate = ExchangeRate(date=utcnow(), buy_rate=buy, sell_rate=sell)
session.add(rate)
session.commit()
session.refresh(rate)
@@ -309,7 +310,7 @@ def _refresh_other_rate(code: str) -> bool:
rate = _fetch_fiat_crc_mid(code)
if rate is None:
return False
_xcrc_cache[code] = (rate, datetime.utcnow())
_xcrc_cache[code] = (rate, utcnow())
_last_known_xcrc[code] = rate
return True
@@ -368,7 +369,7 @@ async def refresh_rates_periodically(
def get_rate_history(session: Session, days: int = 30) -> list[ExchangeRate]:
"""Get historical exchange rates."""
cutoff = datetime.utcnow() - timedelta(days=days)
cutoff = utcnow() - timedelta(days=days)
return list(
session.exec(
select(ExchangeRate)