from __future__ import annotations from datetime import UTC, date, datetime, time, timedelta def ensure_utc(dt: datetime) -> datetime: if dt.tzinfo is None: return dt.replace(tzinfo=UTC) return dt.astimezone(UTC) def parse_date(value: str) -> date: return date.fromisoformat(value) def parse_datetime(value: str) -> datetime: normalized = value.replace("Z", "+00:00") return ensure_utc(datetime.fromisoformat(normalized)) def date_range(start: date, end: date) -> list[date]: days: list[date] = [] current = start while current <= end: days.append(current) current += timedelta(days=1) return days def year_bounds(year: int) -> tuple[date, date]: return date(year, 1, 1), date(year, 12, 31) def date_to_utc_bounds(value: date) -> tuple[datetime, datetime]: start = datetime.combine(value, time.min, tzinfo=UTC) end = datetime.combine(value, time.max, tzinfo=UTC) return start, end