Python package for finding the timezone of any point on earth (coordinates) offline
Advanced functionality for accessing timezone polygon geometry, boundary coordinates, and spatial relationships. These capabilities enable applications requiring detailed geographic data, custom spatial analysis, or integration with GIS systems.
Functions for retrieving complete timezone polygon geometry including boundaries and holes.
def get_geometry(
self,
tz_name: Optional[str] = "",
tz_id: Optional[int] = 0,
use_id: bool = False,
coords_as_pairs: bool = False
) -> List[Union[List[CoordPairs], List[CoordLists]]]:
"""
Retrieve complete geometry of a timezone including all boundary polygons and holes.
Parameters:
- tz_name: Timezone name from timezone_names list (e.g., 'Europe/Berlin')
- tz_id: Timezone ID (index in timezone_names, 0 to nr_of_zones-1)
- use_id: If True, use tz_id parameter instead of tz_name
- coords_as_pairs: If True, return coordinates as [(lng,lat), ...] pairs,
if False, return as ([longitudes], [latitudes]) lists
Returns:
- Multipolygon data structure: [[polygon1, hole1, hole2...], [polygon2, ...], ...]
Each polygon/hole is coordinate pairs or separate longitude/latitude lists
Raises:
- ValueError: If timezone name doesn't exist or tz_id is out of range
- TypeError: If tz_id is not an integer when use_id=True
"""
def get_polygon(
self,
boundary_id: int,
coords_as_pairs: bool = False
) -> List[Union[CoordPairs, CoordLists]]:
"""
Get coordinates of a specific boundary polygon including its holes.
Parameters:
- boundary_id: ID of the boundary polygon (0 to nr_of_polygons-1)
- coords_as_pairs: If True, return coordinates as [(lng,lat), ...] pairs,
if False, return as ([longitudes], [latitudes]) lists
Returns:
- List where first element is boundary polygon, remaining elements are holes
"""
def coords_of(self, boundary_id: int = 0) -> np.ndarray:
"""
Get raw coordinates of a boundary polygon from the dataset.
Parameters:
- boundary_id: ID of the boundary polygon (0 to nr_of_polygons-1)
Returns:
- NumPy array of polygon coordinates in internal format
"""Functions for spatial relationships and polygon testing.
def inside_of_polygon(self, boundary_id: int, x: int, y: int) -> bool:
"""
Check if a point is inside a boundary polygon, accounting for holes.
Parameters:
- boundary_id: ID of the boundary polygon
- x: X-coordinate of point (longitude converted to integer format)
- y: Y-coordinate of point (latitude converted to integer format)
Returns:
- True if point is inside boundary polygon and not in any holes
"""Functions for navigating relationships between zones, boundaries, and coordinates.
def zone_id_of(self, boundary_id: int) -> int:
"""
Get the zone ID that a boundary polygon belongs to.
Parameters:
- boundary_id: ID of the boundary polygon
Returns:
- Zone ID (index in timezone_names)
Raises:
- ValueError: If zone_ids data is not available
"""
def zone_ids_of(self, boundary_ids: np.ndarray) -> np.ndarray:
"""
Get zone IDs for multiple boundary polygons.
Parameters:
- boundary_ids: Array of boundary polygon IDs
Returns:
- Array of corresponding zone IDs
"""
def zone_name_from_id(self, zone_id: int) -> str:
"""
Get timezone name from zone ID.
Parameters:
- zone_id: Zone identifier (0 to nr_of_zones-1)
Returns:
- Timezone name (e.g., 'Europe/Berlin')
Raises:
- ValueError: If zone_id is out of range
"""
def zone_name_from_boundary_id(self, boundary_id: int) -> str:
"""
Get timezone name directly from boundary polygon ID.
Parameters:
- boundary_id: ID of the boundary polygon
Returns:
- Timezone name that the boundary belongs to
"""Functions for working with the spatial indexing system used for performance optimization.
def get_boundaries_in_shortcut(self, *, lng: float, lat: float) -> np.ndarray:
"""
Get all boundary polygon IDs in the shortcut area containing the coordinates.
Parameters:
- lng: Longitude in degrees (-180.0 to 180.0)
- lat: Latitude in degrees (-90.0 to 90.0)
Returns:
- Array of boundary polygon IDs in the H3 hexagon containing the point
"""
def most_common_zone_id(self, *, lng: float, lat: float) -> Optional[int]:
"""
Get the most common zone ID in the shortcut area.
Note: 'Most common' means the zone with boundary polygons having
the most total coordinates in the shortcut area.
Parameters:
- lng: Longitude in degrees (-180.0 to 180.0)
- lat: Latitude in degrees (-90.0 to 90.0)
Returns:
- Zone ID of most common zone, or None if no polygons in area
"""
def unique_zone_id(self, *, lng: float, lat: float) -> Optional[int]:
"""
Get zone ID if unique within the shortcut area.
Parameters:
- lng: Longitude in degrees (-180.0 to 180.0)
- lat: Latitude in degrees (-90.0 to 90.0)
Returns:
- Zone ID if only one zone in area, None if multiple or no zones
"""from timezonefinder import TimezoneFinder
tf = TimezoneFinder()
# Get complete geometry for a timezone
geometry = tf.get_geometry(tz_name='Europe/Berlin', coords_as_pairs=False)
print(f"Europe/Berlin has {len(geometry)} polygon(s)")
for i, polygon_with_holes in enumerate(geometry):
boundary = polygon_with_holes[0] # Boundary polygon
holes = polygon_with_holes[1:] # Hole polygons (if any)
lngs, lats = boundary
print(f"Polygon {i}: {len(lngs)} boundary points, {len(holes)} holes")
# Process each hole
for j, hole in enumerate(holes):
hole_lngs, hole_lats = hole
print(f" Hole {j}: {len(hole_lngs)} points")from timezonefinder import TimezoneFinder
tf = TimezoneFinder()
# Get geometry as coordinate pairs
geometry = tf.get_geometry(tz_name='Europe/Berlin', coords_as_pairs=True)
for i, polygon_with_holes in enumerate(geometry):
boundary = polygon_with_holes[0] # [(lng1, lat1), (lng2, lat2), ...]
holes = polygon_with_holes[1:]
print(f"Polygon {i} boundary:")
print(f" First point: {boundary[0]}")
print(f" Last point: {boundary[-1]}")
print(f" Total points: {len(boundary)}")
for j, hole in enumerate(holes):
print(f" Hole {j}: {len(hole)} points")from timezonefinder import TimezoneFinder
tf = TimezoneFinder()
# Get a specific boundary polygon by ID
boundary_id = 100
polygon_data = tf.get_polygon(boundary_id, coords_as_pairs=False)
boundary = polygon_data[0]
holes = polygon_data[1:]
lngs, lats = boundary
print(f"Boundary {boundary_id}: {len(lngs)} points, {len(holes)} holes")
# Get zone information for this boundary
zone_id = tf.zone_id_of(boundary_id)
zone_name = tf.zone_name_from_id(zone_id)
print(f"Boundary {boundary_id} belongs to zone {zone_id}: {zone_name}")from timezonefinder import TimezoneFinder
import numpy as np
tf = TimezoneFinder()
# Analyze boundaries in a specific area
lng, lat = 13.358, 52.5061 # Berlin coordinates
boundary_ids = tf.get_boundaries_in_shortcut(lng=lng, lat=lat)
print(f"Found {len(boundary_ids)} boundaries near Berlin")
# Group by timezone
zone_ids = tf.zone_ids_of(boundary_ids)
unique_zones = np.unique(zone_ids)
print(f"These boundaries belong to {len(unique_zones)} different timezones:")
for zone_id in unique_zones:
zone_name = tf.zone_name_from_id(zone_id)
count = np.sum(zone_ids == zone_id)
print(f" {zone_name}: {count} boundaries")
# Find most common zone
most_common_id = tf.most_common_zone_id(lng=lng, lat=lat)
if most_common_id is not None:
most_common_name = tf.zone_name_from_id(most_common_id)
print(f"Most common zone: {most_common_name}")from timezonefinder import TimezoneFinder
import json
def timezone_to_geojson(tf, tz_name):
"""Convert timezone geometry to GeoJSON format."""
geometry = tf.get_geometry(tz_name=tz_name, coords_as_pairs=True)
features = []
for i, polygon_with_holes in enumerate(geometry):
boundary = polygon_with_holes[0]
holes = polygon_with_holes[1:]
# GeoJSON coordinates: [exterior_ring, interior_ring1, interior_ring2, ...]
coordinates = [boundary] # Exterior ring
coordinates.extend(holes) # Interior rings (holes)
feature = {
"type": "Feature",
"properties": {
"timezone": tz_name,
"polygon_id": i
},
"geometry": {
"type": "Polygon",
"coordinates": coordinates
}
}
features.append(feature)
return {
"type": "FeatureCollection",
"features": features
}
# Usage
tf = TimezoneFinder()
geojson = timezone_to_geojson(tf, 'Europe/Berlin')
# Save to file
with open('berlin_timezone.geojson', 'w') as f:
json.dump(geojson, f, indent=2)
print(f"Exported {len(geojson['features'])} polygons for Europe/Berlin")from timezonefinder import TimezoneFinder
from timezonefinder.utils import coord2int
tf = TimezoneFinder()
def find_overlapping_zones(lng, lat, radius_degrees=0.1):
"""Find all timezones within a radius of a point."""
# Sample points in a grid around the center
step = radius_degrees / 10
zones = set()
for dlng in [-radius_degrees, 0, radius_degrees]:
for dlat in [-radius_degrees, 0, radius_degrees]:
test_lng = lng + dlng
test_lat = lat + dlat
# Get boundaries in this area
boundaries = tf.get_boundaries_in_shortcut(lng=test_lng, lat=test_lat)
# Convert coordinates for polygon testing
x = coord2int(test_lng)
y = coord2int(test_lat)
# Test each boundary
for boundary_id in boundaries:
if tf.inside_of_polygon(boundary_id, x, y):
zone_name = tf.zone_name_from_boundary_id(boundary_id)
zones.add(zone_name)
return list(zones)
# Find zones near a border area
border_zones = find_overlapping_zones(lng=8.5, lat=47.5, radius_degrees=0.5)
print(f"Zones near Swiss-German border: {border_zones}")Install with Tessl CLI
npx tessl i tessl/pypi-timezonefinder