"""Timezone utilities used by the temp spec application.""" from __future__ import annotations from datetime import datetime, date, time, timedelta, timezone TAIWAN_TZ = timezone(timedelta(hours=8)) def now_taiwan() -> datetime: """Return current datetime in Taiwan time (aware).""" return datetime.now(TAIWAN_TZ) def now_utc() -> datetime: """Return current datetime in UTC (aware).""" return datetime.now(timezone.utc) def taiwan_now() -> datetime: """Return current datetime in Taiwan time (naive).""" return now_taiwan().replace(tzinfo=None) def to_taiwan_time(dt: datetime | date | None) -> datetime | None: """Convert a datetime/date (naive or aware) to Taiwan time (aware).""" if dt is None: return None # Promote date to datetime if isinstance(dt, date) and not isinstance(dt, datetime): dt = datetime.combine(dt, time.min) # Treat naive timestamps as UTC if dt.tzinfo is None: dt = dt.replace(tzinfo=timezone.utc) return dt.astimezone(TAIWAN_TZ) def to_utc_time(dt: datetime | date | None) -> datetime | None: """Convert a datetime/date (naive or aware) to UTC (aware).""" if dt is None: return None if isinstance(dt, date) and not isinstance(dt, datetime): dt = datetime.combine(dt, time.min).replace(tzinfo=TAIWAN_TZ) if dt.tzinfo is None: dt = dt.replace(tzinfo=TAIWAN_TZ) return dt.astimezone(timezone.utc) def format_taiwan_time(dt: datetime | date | None, format_str: str = "%Y-%m-%d %H:%M:%S") -> str: """Format a datetime/date using Taiwan time.""" if dt is None: return "" tpe_dt = to_taiwan_time(dt) return tpe_dt.strftime(format_str) def parse_taiwan_time(time_str: str, format_str: str = "%Y-%m-%d %H:%M:%S") -> datetime: """Parse a string as Taiwan time (aware).""" naive_dt = datetime.strptime(time_str, format_str) return naive_dt.replace(tzinfo=TAIWAN_TZ)