from __future__ import annotations from datetime import datetime, timezone from typing import Optional def _now_iso() -> str: return datetime.now(timezone.utc).isoformat() def _parse_iso_time(value: str) -> Optional[datetime]: if not isinstance(value, str) or not value.strip(): return None text = value.strip() if text.endswith("Z"): text = text[:-1] + "+00:00" try: parsed = datetime.fromisoformat(text) except ValueError: return None if parsed.tzinfo is None: parsed = parsed.replace(tzinfo=timezone.utc) return parsed def _coerce_epoch_seconds(value: object) -> Optional[int]: if isinstance(value, bool): return None if isinstance(value, (int, float)): return int(value) if isinstance(value, str): stripped = value.strip() if stripped.isdigit(): return int(stripped) return None