"""Publication dates from RSS/Atom/APIs, normalized to aware UTC datetimes.""" from datetime import datetime, timezone from email.utils import parsedate_to_datetime import re def parse_published(value): """Accept Unix seconds/milliseconds, ISO 8601 or RFC 2822; invalid -> None. Dates without a timezone are interpreted as UTC, not the host's local zone. """ if value is None or not str(value).strip(): return None text = str(value).strip() try: if re.fullmatch(r"\d{4}", text): return None # A bare year is not a Unix timestamp. if re.fullmatch(r"\d{8}", text): return datetime.strptime(text, "%Y%m%d").replace(tzinfo=timezone.utc) if re.fullmatch(r"-?\d+(?:\.\d+)?", text): stamp = float(text) if abs(stamp) >= 10**12: stamp /= 1000 return datetime.fromtimestamp(stamp, timezone.utc) try: dt = datetime.fromisoformat(text.replace("Z", "+00:00")) except ValueError: dt = parsedate_to_datetime(text) if dt.tzinfo is None: dt = dt.replace(tzinfo=timezone.utc) return dt.astimezone(timezone.utc) except (ValueError, TypeError, OverflowError, OSError): return None