fix: fix timezone handling across backend and frontend (v0.3.1)
- Add tz.py with local_strftime/to_local helpers that read system.timezone from DB and convert UTC datetimes to venue local time before formatting - Fix all strftime() calls in orders.py, reports.py, printer_service.py that were formatting UTC datetimes without timezone conversion - Fix get_order endpoint returning raw dicts without Z suffix on datetimes, causing JS new Date() to treat timestamps as local instead of UTC - Fix fmtDate() in tokens.js that stripped the T separator before parsing, breaking UTC-to-local conversion for all report date displays - Make open/partially_paid table chips more visually distinct on dashboard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
39
local_backend/tz.py
Normal file
39
local_backend/tz.py
Normal file
@@ -0,0 +1,39 @@
|
||||
"""Timezone utilities for converting UTC datetimes to the venue's local time."""
|
||||
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from database import SessionLocal
|
||||
from models.settings import PosSettings
|
||||
|
||||
_FALLBACK = "Europe/Athens"
|
||||
|
||||
|
||||
def _get_tz_name() -> str:
|
||||
db = SessionLocal()
|
||||
try:
|
||||
row = db.query(PosSettings).filter(PosSettings.key == "system.timezone").first()
|
||||
return row.value if row and row.value else _FALLBACK
|
||||
except Exception:
|
||||
return _FALLBACK
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def to_local(dt: datetime) -> datetime:
|
||||
"""Convert a UTC-aware datetime to the venue's configured local timezone."""
|
||||
if dt is None:
|
||||
return dt
|
||||
if dt.tzinfo is None:
|
||||
dt = dt.replace(tzinfo=timezone.utc)
|
||||
try:
|
||||
tz = ZoneInfo(_get_tz_name())
|
||||
except ZoneInfoNotFoundError:
|
||||
tz = ZoneInfo(_FALLBACK)
|
||||
return dt.astimezone(tz)
|
||||
|
||||
|
||||
def local_strftime(dt: datetime, fmt: str) -> str:
|
||||
"""Format a UTC-aware datetime in local time using the venue's timezone."""
|
||||
if dt is None:
|
||||
return "—"
|
||||
return to_local(dt).strftime(fmt)
|
||||
Reference in New Issue
Block a user