import re from datetime import date, datetime from typing import Any, Iterable, TypeVar T = TypeVar("T") def parse_date(value: Any) -> date | None: if value is None or value == "": return None if isinstance(value, datetime): return value.date() if isinstance(value, date): return value text = str(value).strip() if not text: return None # `%d/%m/%Y %H:%M` is how the TARIC daily publications write every date. for date_format in ( "%Y-%m-%d", "%d-%m-%Y", "%d/%m/%Y", "%d/%m/%Y %H:%M", "%Y/%m/%d", "%d.%m.%Y", "%Y%m%d", ): try: return datetime.strptime(text, date_format).date() except ValueError: continue try: return datetime.fromisoformat(text).date() except ValueError: return None def normalize_ws(value: Any) -> str | None: if value is None: return None text = re.sub(r"\s+", " ", str(value)).strip() return text or None def parse_number(value: Any) -> float | None: if value is None or value == "": return None if isinstance(value, (int, float)): return float(value) text = str(value).strip().replace(" ", "").replace(" ", "") if not text: return None if "," in text and "." in text: text = text.replace(".", "") if text.rfind(",") > text.rfind(".") else text text = text.replace(",", ".") if text.count(".") <= 1 else text.replace(",", "") else: text = text.replace(",", ".") try: return float(re.sub(r"[^0-9.\-]", "", text)) except ValueError: return None def normalize_country(value: Any) -> str | None: if value is None: return None text = re.sub(r"[^A-Za-z]", "", str(value)).upper() if len(text) < 2: return None return text[:2] def dedupe(items: Iterable[T]) -> list[T]: seen: set[T] = set() result: list[T] = [] for item in items: if item not in seen: seen.add(item) result.append(item) return result