0
# Core Timezone Lookup
1
2
Primary timezone determination classes providing both full-featured polygon-based precision checking and lightweight approximation modes. These classes form the foundation of timezonefinder's timezone lookup capabilities.
3
4
## Capabilities
5
6
### TimezoneFinder Class
7
8
Full-featured timezone finder with polygon-based precision checking. Uses precomputed shortcuts to reduce polygon testing while maintaining accuracy through precise point-in-polygon algorithms.
9
10
```python { .api }
11
class TimezoneFinder:
12
def __init__(self, bin_file_location: Optional[str] = None, in_memory: bool = False):
13
"""
14
Initialize TimezoneFinder instance.
15
16
Parameters:
17
- bin_file_location: Path to binary data files, None for package data
18
- in_memory: Whether to load coordinate data into memory for faster access
19
"""
20
21
def timezone_at(self, *, lng: float, lat: float) -> Optional[str]:
22
"""
23
Find timezone for given coordinates, including ocean timezones.
24
25
Parameters:
26
- lng: Longitude in degrees (-180.0 to 180.0)
27
- lat: Latitude in degrees (-90.0 to 90.0)
28
29
Returns:
30
- Timezone name (e.g., 'Europe/Berlin', 'Etc/GMT+5') or None
31
"""
32
33
def timezone_at_land(self, *, lng: float, lat: float) -> Optional[str]:
34
"""
35
Find land timezone only, excluding ocean timezones.
36
37
Parameters:
38
- lng: Longitude in degrees (-180.0 to 180.0)
39
- lat: Latitude in degrees (-90.0 to 90.0)
40
41
Returns:
42
- Land timezone name or None for ocean locations
43
"""
44
45
def unique_timezone_at(self, *, lng: float, lat: float) -> Optional[str]:
46
"""
47
Find timezone if unique within the shortcut area.
48
49
Parameters:
50
- lng: Longitude in degrees (-180.0 to 180.0)
51
- lat: Latitude in degrees (-90.0 to 90.0)
52
53
Returns:
54
- Timezone name if unique in area, None if multiple or no zones
55
"""
56
57
def certain_timezone_at(self, *, lng: float, lat: float) -> Optional[str]:
58
"""
59
Find timezone with exhaustive polygon checking.
60
61
Note: Less performant than timezone_at(), only useful for custom timezone data
62
with incomplete coverage.
63
64
Parameters:
65
- lng: Longitude in degrees (-180.0 to 180.0)
66
- lat: Latitude in degrees (-90.0 to 90.0)
67
68
Returns:
69
- Timezone name if point is certainly within a polygon, None otherwise
70
"""
71
```
72
73
#### Properties and Utility Methods
74
75
```python { .api }
76
@property
77
def nr_of_zones(self) -> int:
78
"""Number of timezones in the dataset."""
79
80
@property
81
def nr_of_polygons(self) -> int:
82
"""Number of boundary polygons in the dataset."""
83
84
@property
85
def nr_of_holes(self) -> int:
86
"""Number of hole polygons in the dataset."""
87
88
def zone_name_from_id(self, zone_id: int) -> str:
89
"""
90
Get timezone name from zone ID.
91
92
Parameters:
93
- zone_id: Zone identifier (0 to nr_of_zones-1)
94
95
Returns:
96
- Timezone name
97
98
Raises:
99
- ValueError: If zone_id is invalid
100
"""
101
102
def zone_id_of(self, boundary_id: int) -> int:
103
"""
104
Get the zone ID that a boundary polygon belongs to.
105
106
Parameters:
107
- boundary_id: ID of the boundary polygon
108
109
Returns:
110
- Zone ID (index in timezone_names)
111
112
Raises:
113
- ValueError: If zone_ids data is not available
114
"""
115
116
def zone_ids_of(self, boundary_ids: np.ndarray) -> np.ndarray:
117
"""
118
Get zone IDs for multiple boundary polygons.
119
120
Parameters:
121
- boundary_ids: Array of boundary polygon IDs
122
123
Returns:
124
- Array of corresponding zone IDs
125
"""
126
127
def zone_name_from_boundary_id(self, boundary_id: int) -> str:
128
"""
129
Get timezone name from boundary polygon ID.
130
131
Parameters:
132
- boundary_id: ID of the boundary polygon
133
134
Returns:
135
- Timezone name
136
"""
137
138
def coords_of(self, boundary_id: int = 0) -> np.ndarray:
139
"""
140
Get coordinates of a boundary polygon from the FlatBuffers collection.
141
142
Parameters:
143
- boundary_id: Index of the polygon (default: 0)
144
145
Returns:
146
- Array of coordinates
147
"""
148
149
def get_boundaries_in_shortcut(self, *, lng: float, lat: float) -> np.ndarray:
150
"""
151
Get boundary polygon IDs in the shortcut area for given coordinates.
152
153
Parameters:
154
- lng: Longitude in degrees (-180.0 to 180.0)
155
- lat: Latitude in degrees (-90.0 to 90.0)
156
157
Returns:
158
- Array of boundary polygon IDs
159
"""
160
161
def most_common_zone_id(self, *, lng: float, lat: float) -> Optional[int]:
162
"""
163
Get the most common zone ID in the shortcut area for given coordinates.
164
165
Note: Boundary polygons are sorted by zone, with zones having more polygon
166
coordinates coming last.
167
168
Parameters:
169
- lng: Longitude in degrees (-180.0 to 180.0)
170
- lat: Latitude in degrees (-90.0 to 90.0)
171
172
Returns:
173
- Most common zone ID or None if no polygons exist in shortcut
174
"""
175
176
def unique_zone_id(self, *, lng: float, lat: float) -> Optional[int]:
177
"""
178
Get unique zone ID in shortcut area if only one zone exists.
179
180
Parameters:
181
- lng: Longitude in degrees (-180.0 to 180.0)
182
- lat: Latitude in degrees (-90.0 to 90.0)
183
184
Returns:
185
- Unique zone ID or None if no polygons or multiple zones exist
186
"""
187
188
def inside_of_polygon(self, boundary_id: int, x: int, y: int) -> bool:
189
"""
190
Check if a point is inside a boundary polygon.
191
192
Note: Checks bounding boxes first for efficiency, then holes, then boundary.
193
194
Parameters:
195
- boundary_id: ID of the boundary polygon
196
- x: X-coordinate of the point
197
- y: Y-coordinate of the point
198
199
Returns:
200
- True if point is inside boundary polygon, False if outside or in hole
201
"""
202
203
@staticmethod
204
def using_numba() -> bool:
205
"""Check if Numba JIT compilation is being used."""
206
207
@staticmethod
208
def using_clang_pip() -> bool:
209
"""Check if compiled C point-in-polygon implementation is being used."""
210
```
211
212
### TimezoneFinderL Class
213
214
Lightweight timezone finder for fast approximations. Uses only precomputed shortcuts without polygon checking, providing the most common timezone in each area.
215
216
```python { .api }
217
class TimezoneFinderL:
218
def __init__(self, bin_file_location: Optional[Union[str, Path]] = None, in_memory: bool = False):
219
"""
220
Initialize TimezoneFinderL instance.
221
222
Note: Inherits constructor from AbstractTimezoneFinder.
223
224
Parameters:
225
- bin_file_location: Path to binary data files, None for package data
226
- in_memory: Ignored for TimezoneFinderL, exists for compatibility
227
"""
228
229
def timezone_at(self, *, lng: float, lat: float) -> Optional[str]:
230
"""
231
Instantly return the most common timezone in the shortcut area.
232
233
Note: 'Most common' means the zone with boundary polygons having the most
234
coordinates in the corresponding shortcut area.
235
236
Parameters:
237
- lng: Longitude in degrees (-180.0 to 180.0)
238
- lat: Latitude in degrees (-90.0 to 90.0)
239
240
Returns:
241
- Most common timezone name in area or None if no polygons exist
242
"""
243
244
def timezone_at_land(self, *, lng: float, lat: float) -> Optional[str]:
245
"""
246
Find land timezone only, excluding ocean timezones.
247
248
Inherited from AbstractTimezoneFinder. Returns None when an ocean
249
timezone would be matched.
250
251
Parameters:
252
- lng: Longitude in degrees (-180.0 to 180.0)
253
- lat: Latitude in degrees (-90.0 to 90.0)
254
255
Returns:
256
- Land timezone name or None for ocean locations
257
"""
258
```
259
260
## Usage Examples
261
262
### Basic Instance Usage
263
264
```python
265
from timezonefinder import TimezoneFinder
266
267
# Create instance
268
tf = TimezoneFinder()
269
270
# Single lookup
271
tz = tf.timezone_at(lng=13.358, lat=52.5061)
272
print(tz) # 'Europe/Berlin'
273
274
# Land timezone only
275
land_tz = tf.timezone_at_land(lng=0.0, lat=0.0)
276
print(land_tz) # None (ocean location)
277
```
278
279
### High-Performance Usage
280
281
```python
282
from timezonefinder import TimezoneFinder
283
284
# Load data into memory for faster repeated queries
285
tf = TimezoneFinder(in_memory=True)
286
287
# Check performance capabilities
288
print(f"Using Numba: {tf.using_numba()}")
289
print(f"Using C extension: {tf.using_clang_pip()}")
290
291
# Batch processing
292
coordinates = [
293
(13.358, 52.5061), # Berlin
294
(-74.0060, 40.7128), # New York
295
(139.6917, 35.6895) # Tokyo
296
]
297
298
for lng, lat in coordinates:
299
tz = tf.timezone_at(lng=lng, lat=lat)
300
print(f"({lat:.3f}, {lng:.3f}) -> {tz}")
301
```
302
303
### Lightweight Approximation
304
305
```python
306
from timezonefinder import TimezoneFinderL
307
308
# Fast approximation without polygon checking
309
tfl = TimezoneFinderL()
310
311
# Quick timezone suggestion
312
tz = tfl.timezone_at(lng=13.358, lat=52.5061)
313
print(tz) # 'Europe/Berlin' (most common in area)
314
```
315
316
### Thread-Safe Usage
317
318
```python
319
import threading
320
from timezonefinder import TimezoneFinder
321
322
def worker(coordinates, results, thread_id):
323
# Each thread gets its own instance
324
tf = TimezoneFinder(in_memory=True)
325
326
for i, (lng, lat) in enumerate(coordinates):
327
tz = tf.timezone_at(lng=lng, lat=lat)
328
results[thread_id][i] = tz
329
330
# Prepare data for multiple threads
331
all_coords = [(lng, lat) for lng in range(-180, 180, 10)
332
for lat in range(-90, 90, 10)]
333
334
threads = []
335
results = [{} for _ in range(4)]
336
337
# Split work across threads
338
chunk_size = len(all_coords) // 4
339
for i in range(4):
340
start = i * chunk_size
341
end = start + chunk_size if i < 3 else len(all_coords)
342
coords_chunk = all_coords[start:end]
343
344
thread = threading.Thread(
345
target=worker,
346
args=(coords_chunk, results, i)
347
)
348
threads.append(thread)
349
thread.start()
350
351
# Wait for completion
352
for thread in threads:
353
thread.join()
354
```