File size: 2,106 Bytes
a9710f3
 
c2ea771
a9710f3
 
 
 
 
 
 
 
 
 
 
 
 
 
b3ba377
 
 
 
 
 
 
 
 
 
a9710f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2ea771
a9710f3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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