""" utils/dates.py — Date parsing and formatting utilities Functions: - parse_date(s): Parse common date formats to datetime - format_date(s): Format date to readable string """ from __future__ import annotations from datetime import datetime from typing import Any, Optional def parse_date(s: Any) -> Optional[datetime]: """ Parse common date formats to datetime object. Supports: - ISO 8601: 2024-12-31T23:59:59 - Date only: 2024-12-31 - UK format: 31/12/2024 Args: s: Date string or datetime object Returns: datetime object or None if parsing fails """ if not s: return None if isinstance(s, datetime): return s # Try common formats s_str = str(s) # ISO 8601 with time: 2024-12-31T23:59:59 if 'T' in s_str and len(s_str) >= 19: try: return datetime.strptime(s_str[:19], "%Y-%m-%dT%H:%M:%S") except Exception: pass # ISO 8601 date only: 2024-12-31 if len(s_str) >= 10 and s_str[4:5] == '-' and s_str[7:8] == '-': try: return datetime.strptime(s_str[:10], "%Y-%m-%d") except Exception: pass # UK format: 31/12/2024 if '/' in s_str and len(s_str) >= 10: try: return datetime.strptime(s_str[:10], "%d/%m/%Y") except Exception: pass return None def format_date(s: Any, *, include_time: bool = False) -> str: """ Format date to human-readable string. Args: s: Date string, datetime object, or None include_time: If True, include time if available Returns: Formatted date string or "—" if parsing fails Examples: >>> format_date("2024-12-31") '2024-12-31' >>> format_date("2024-12-31T14:30:00", include_time=True) '2024-12-31 14:30:00' """ d = parse_date(s) if not d: return str(s) if s else "—" # Auto-detect if time should be included has_time = d.hour or d.minute or d.second if include_time or has_time: return d.strftime("%Y-%m-%d %H:%M:%S") else: return d.strftime("%Y-%m-%d")