from __future__ import annotations from datetime import UTC, datetime, timedelta, timezone from zoneinfo import ZoneInfo, ZoneInfoNotFoundError TIME_FORMAT = "%Y-%m-%d %H:%M:%S.%f" def resolve_timezone(timezone_name: str): try: return ZoneInfo(timezone_name) except ZoneInfoNotFoundError: fallback_mapping = { "Asia/Shanghai": timezone(timedelta(hours=8)), "Asia/Hong_Kong": timezone(timedelta(hours=8)), "UTC": UTC, } return fallback_mapping.get(timezone_name, UTC) def format_now(timezone_name: str) -> str: current = datetime.now(resolve_timezone(timezone_name)) return current.strftime(TIME_FORMAT)[:-3] def parse_timestamp(value: str | None) -> datetime | None: if not value: return None try: return datetime.strptime(value, TIME_FORMAT) except ValueError: return None def compute_duration_ms(started_at: str | None, finished_at: str | None) -> int | None: started = parse_timestamp(started_at) finished = parse_timestamp(finished_at) if not started or not finished: return None duration_ms = int((finished - started).total_seconds() * 1000) return max(duration_ms, 0)