app/clock.py
Rama main · réplica de lectura del repositorio original.
"""The app's idea of "today".
A container runs in UTC, and this app is full of date-boundary decisions —
whether a trade is in the future, which financial year is current, what the
calendar highlights. Read from UTC every one is wrong for the first hours of an
Australian morning.
So no date decision calls `datetime.date.today()`; they call `today()` here,
which answers in the configured zone. The zone is process-wide rather than an
argument: decisions.md #82.
Timestamps stay in UTC — `created_at`, session expiry and audit fields are
instants, not dates. Only calendar decisions belong here.
"""
from __future__ import annotations
import datetime as dt
from zoneinfo import ZoneInfo
from .settings import DEFAULT_TIMEZONE
_zone = ZoneInfo(DEFAULT_TIMEZONE)
def configure(name: str) -> None:
"""Point the clock at a timezone. Called once, at startup, from settings.
Raises if the zone is unknown, so a typo in config.yaml fails at boot
rather than silently serving dates from somewhere else.
"""
global _zone
_zone = ZoneInfo(name)
def zone() -> ZoneInfo:
return _zone
def today() -> dt.date:
"""The current date where the portfolio lives."""
return dt.datetime.now(_zone).date()
def now() -> dt.datetime:
"""The current instant, as an aware datetime in the configured zone."""
return dt.datetime.now(_zone)