zip2info 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zip2info/__init__.py +95 -0
- zip2info/_data.py +38710 -0
- zip2info-1.0.0.dist-info/METADATA +118 -0
- zip2info-1.0.0.dist-info/RECORD +6 -0
- zip2info-1.0.0.dist-info/WHEEL +4 -0
- zip2info-1.0.0.dist-info/licenses/LICENSE +21 -0
zip2info/__init__.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from zip2info._data import TIMEZONES, ZIP_INFO
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass(frozen=True, slots=True)
|
|
8
|
+
class ZipInfo:
|
|
9
|
+
"""Metadata for a US ZIP code."""
|
|
10
|
+
|
|
11
|
+
zipcode: int
|
|
12
|
+
timezone: str
|
|
13
|
+
latitude: float
|
|
14
|
+
longitude: float
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _normalize_zipcode(zipcode: str | int) -> Optional[int]:
|
|
18
|
+
try:
|
|
19
|
+
return int(zipcode)
|
|
20
|
+
except (ValueError, TypeError):
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def timezone(zipcode: str | int) -> Optional[str]:
|
|
25
|
+
"""
|
|
26
|
+
Return the IANA timezone for a US ZIP code.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
zipcode: ZIP code as a string or integer.
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Timezone string (for example, ``America/New_York``) or ``None``.
|
|
33
|
+
"""
|
|
34
|
+
zip_int = _normalize_zipcode(zipcode)
|
|
35
|
+
if zip_int is None:
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
record = ZIP_INFO.get(zip_int)
|
|
39
|
+
if record is None:
|
|
40
|
+
return None
|
|
41
|
+
tz_idx, _, _ = record
|
|
42
|
+
return TIMEZONES[tz_idx]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def coordinates(zipcode: str | int) -> Optional[tuple[float, float]]:
|
|
46
|
+
"""
|
|
47
|
+
Return centroid latitude and longitude for a US ZIP code.
|
|
48
|
+
|
|
49
|
+
Coordinates come from the generated ZIP metadata dataset.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
zipcode: ZIP code as a string or integer.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
``(latitude, longitude)`` or ``None``.
|
|
56
|
+
"""
|
|
57
|
+
zip_int = _normalize_zipcode(zipcode)
|
|
58
|
+
if zip_int is None:
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
record = ZIP_INFO.get(zip_int)
|
|
62
|
+
if record is None:
|
|
63
|
+
return None
|
|
64
|
+
_, latitude, longitude = record
|
|
65
|
+
return latitude, longitude
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def info(zipcode: str | int) -> Optional[ZipInfo]:
|
|
69
|
+
"""
|
|
70
|
+
Return timezone and coordinate metadata for a US ZIP code.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
zipcode: ZIP code as a string or integer.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
``ZipInfo`` when timezone data exists, otherwise ``None``.
|
|
77
|
+
"""
|
|
78
|
+
zip_int = _normalize_zipcode(zipcode)
|
|
79
|
+
if zip_int is None:
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
record = ZIP_INFO.get(zip_int)
|
|
83
|
+
if record is None:
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
tz_idx, latitude, longitude = record
|
|
87
|
+
return ZipInfo(
|
|
88
|
+
zipcode=zip_int,
|
|
89
|
+
timezone=TIMEZONES[tz_idx],
|
|
90
|
+
latitude=latitude,
|
|
91
|
+
longitude=longitude,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
__all__ = ["ZipInfo", "coordinates", "info", "timezone"]
|