Spaces:
Configuration error
Configuration error
File size: 2,462 Bytes
aa15bce |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
"""Persist and expose the user's preferred timezone."""
from __future__ import annotations
import threading
from pathlib import Path
from typing import Optional
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
from ..logging_config import logger
class TimezoneStore:
"""Stores a single timezone string supplied by the client UI."""
def __init__(self, path: Path):
self._path = path
self._lock = threading.Lock()
self._cached: Optional[str] = None
self._load()
def _load(self) -> None:
try:
value = self._path.read_text(encoding="utf-8").strip()
except FileNotFoundError:
self._cached = None
return
except Exception as exc: # pragma: no cover - defensive
logger.warning("failed to read timezone file", extra={"error": str(exc)})
self._cached = None
return
self._cached = value or None
def get_timezone(self, default: str = "UTC") -> str:
with self._lock:
return self._cached or default
def set_timezone(self, timezone_name: str) -> None:
validated = self._validate(timezone_name)
with self._lock:
self._path.parent.mkdir(parents=True, exist_ok=True)
self._path.write_text(validated, encoding="utf-8")
self._cached = validated
logger.info("updated timezone preference", extra={"timezone": validated})
def clear(self) -> None:
with self._lock:
self._cached = None
try:
if self._path.exists():
self._path.unlink()
except Exception as exc: # pragma: no cover - defensive
logger.warning("failed to clear timezone file", extra={"error": str(exc)})
def _validate(self, timezone_name: str) -> str:
candidate = (timezone_name or "").strip()
if not candidate:
raise ValueError("timezone must be a non-empty string")
try:
ZoneInfo(candidate)
except ZoneInfoNotFoundError as exc:
raise ValueError(f"Unknown timezone: {candidate}") from exc
return candidate
_DATA_DIR = Path(__file__).resolve().parent.parent / "data"
_TIMEZONE_PATH = _DATA_DIR / "timezone.txt"
_timezone_store = TimezoneStore(_TIMEZONE_PATH)
def get_timezone_store() -> TimezoneStore:
return _timezone_store
__all__ = ["TimezoneStore", "get_timezone_store"]
|