- 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>
40 lines
1.1 KiB
Python
40 lines
1.1 KiB
Python
"""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)
|