Исходный код app.clock

"""Dataset clock: maps wall-clock time onto the dataset's timeline.

The dataset is one service day, 2026-01-06, with naive Moscow-local timestamps. Live telemetry (the
emulator, real terminals) carries today's wall-clock time. Every component converts through one
``DatasetClock``, so live and historical data share a single timeline::

    dataset_time = anchor_dataset + (wall_time - anchor_wall) * speed

Default anchor: at startup, the current Moscow time of day on the dataset day, speed 1 — the demo
shows the dataset's vehicles "as of now". ``GET /clock`` publishes the anchor, so external drivers
(``infra/emulator_replay.py --clock-url``) replay tracks on exactly this timeline.
"""

from __future__ import annotations

import time
from dataclasses import dataclass
from datetime import date, datetime, timedelta, timezone

MSK = timezone(timedelta(hours=3))
DATASET_DAY = date(2026, 1, 6)


[документация] @dataclass(frozen=True, slots=True) class DatasetClock: anchor_wall: float # Unix seconds anchor_dataset: datetime # naive, Moscow-local, like the dataset speed: float = 1.0 def __post_init__(self) -> None: if self.speed <= 0: raise ValueError(f"clock speed must be positive, got {self.speed}") if self.anchor_dataset.tzinfo is not None: raise ValueError("anchor_dataset must be naive (dataset timestamps carry no timezone)")
[документация] @classmethod def starting_at(cls, dataset_time: datetime | None = None, *, day: date = DATASET_DAY, speed: float = 1.0, wall: float | None = None) -> DatasetClock: """A clock whose dataset time at ``wall`` (default: now) is ``dataset_time`` (default: the current Moscow time of day on ``day``).""" wall = time.time() if wall is None else wall if dataset_time is None: dataset_time = datetime.combine(day, datetime.fromtimestamp(wall, MSK).time()) return cls(anchor_wall=wall, anchor_dataset=dataset_time, speed=speed)
[документация] def to_dataset(self, wall: float) -> datetime: return self.anchor_dataset + timedelta(seconds=(wall - self.anchor_wall) * self.speed)
[документация] def to_wall(self, dataset_time: datetime) -> float: return self.anchor_wall + (dataset_time - self.anchor_dataset).total_seconds() / self.speed
[документация] def now(self) -> datetime: return self.to_dataset(time.time())