CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-timezonefinder

Python package for finding the timezone of any point on earth (coordinates) offline

Overview
Eval results
Files

core-lookup.mddocs/

Core Timezone Lookup

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.

Capabilities

TimezoneFinder Class

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.

class TimezoneFinder:
    def __init__(self, bin_file_location: Optional[str] = None, in_memory: bool = False):
        """
        Initialize TimezoneFinder instance.
        
        Parameters:
        - bin_file_location: Path to binary data files, None for package data
        - in_memory: Whether to load coordinate data into memory for faster access
        """
        
    def timezone_at(self, *, lng: float, lat: float) -> Optional[str]:
        """
        Find timezone for given coordinates, including ocean timezones.
        
        Parameters:
        - lng: Longitude in degrees (-180.0 to 180.0)
        - lat: Latitude in degrees (-90.0 to 90.0)
        
        Returns:
        - Timezone name (e.g., 'Europe/Berlin', 'Etc/GMT+5') or None
        """
        
    def timezone_at_land(self, *, lng: float, lat: float) -> Optional[str]:
        """
        Find land timezone only, excluding ocean timezones.
        
        Parameters:
        - lng: Longitude in degrees (-180.0 to 180.0)
        - lat: Latitude in degrees (-90.0 to 90.0)
        
        Returns:
        - Land timezone name or None for ocean locations
        """
        
    def unique_timezone_at(self, *, lng: float, lat: float) -> Optional[str]:
        """
        Find timezone 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:
        - Timezone name if unique in area, None if multiple or no zones
        """
        
    def certain_timezone_at(self, *, lng: float, lat: float) -> Optional[str]:
        """
        Find timezone with exhaustive polygon checking.
        
        Note: Less performant than timezone_at(), only useful for custom timezone data
        with incomplete coverage.
        
        Parameters:
        - lng: Longitude in degrees (-180.0 to 180.0)
        - lat: Latitude in degrees (-90.0 to 90.0)
        
        Returns:
        - Timezone name if point is certainly within a polygon, None otherwise
        """

Properties and Utility Methods

@property
def nr_of_zones(self) -> int:
    """Number of timezones in the dataset."""

@property 
def nr_of_polygons(self) -> int:
    """Number of boundary polygons in the dataset."""

@property
def nr_of_holes(self) -> int:
    """Number of hole polygons in the dataset."""

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
    
    Raises:
    - ValueError: If zone_id is invalid
    """

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_boundary_id(self, boundary_id: int) -> str:
    """
    Get timezone name from boundary polygon ID.
    
    Parameters:
    - boundary_id: ID of the boundary polygon
    
    Returns:
    - Timezone name
    """

def coords_of(self, boundary_id: int = 0) -> np.ndarray:
    """
    Get coordinates of a boundary polygon from the FlatBuffers collection.
    
    Parameters:
    - boundary_id: Index of the polygon (default: 0)
    
    Returns:
    - Array of coordinates
    """

def get_boundaries_in_shortcut(self, *, lng: float, lat: float) -> np.ndarray:
    """
    Get boundary polygon IDs in the shortcut area for given 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
    """

def most_common_zone_id(self, *, lng: float, lat: float) -> Optional[int]:
    """
    Get the most common zone ID in the shortcut area for given coordinates.
    
    Note: Boundary polygons are sorted by zone, with zones having more polygon 
    coordinates coming last.
    
    Parameters:
    - lng: Longitude in degrees (-180.0 to 180.0)
    - lat: Latitude in degrees (-90.0 to 90.0)
    
    Returns:
    - Most common zone ID or None if no polygons exist in shortcut
    """

def unique_zone_id(self, *, lng: float, lat: float) -> Optional[int]:
    """
    Get unique zone ID in shortcut area if only one zone exists.
    
    Parameters:
    - lng: Longitude in degrees (-180.0 to 180.0)
    - lat: Latitude in degrees (-90.0 to 90.0)
    
    Returns:
    - Unique zone ID or None if no polygons or multiple zones exist
    """

def inside_of_polygon(self, boundary_id: int, x: int, y: int) -> bool:
    """
    Check if a point is inside a boundary polygon.
    
    Note: Checks bounding boxes first for efficiency, then holes, then boundary.
    
    Parameters:
    - boundary_id: ID of the boundary polygon
    - x: X-coordinate of the point
    - y: Y-coordinate of the point
    
    Returns:
    - True if point is inside boundary polygon, False if outside or in hole
    """

@staticmethod
def using_numba() -> bool:
    """Check if Numba JIT compilation is being used."""

@staticmethod  
def using_clang_pip() -> bool:
    """Check if compiled C point-in-polygon implementation is being used."""

TimezoneFinderL Class

Lightweight timezone finder for fast approximations. Uses only precomputed shortcuts without polygon checking, providing the most common timezone in each area.

class TimezoneFinderL:
    def __init__(self, bin_file_location: Optional[Union[str, Path]] = None, in_memory: bool = False):
        """
        Initialize TimezoneFinderL instance.
        
        Note: Inherits constructor from AbstractTimezoneFinder.
        
        Parameters:
        - bin_file_location: Path to binary data files, None for package data  
        - in_memory: Ignored for TimezoneFinderL, exists for compatibility
        """
        
    def timezone_at(self, *, lng: float, lat: float) -> Optional[str]:
        """
        Instantly return the most common timezone in the shortcut area.
        
        Note: 'Most common' means the zone with boundary polygons having the most
        coordinates in the corresponding shortcut area.
        
        Parameters:
        - lng: Longitude in degrees (-180.0 to 180.0)
        - lat: Latitude in degrees (-90.0 to 90.0)
        
        Returns:
        - Most common timezone name in area or None if no polygons exist
        """
        
    def timezone_at_land(self, *, lng: float, lat: float) -> Optional[str]:
        """
        Find land timezone only, excluding ocean timezones.
        
        Inherited from AbstractTimezoneFinder. Returns None when an ocean 
        timezone would be matched.
        
        Parameters:
        - lng: Longitude in degrees (-180.0 to 180.0)
        - lat: Latitude in degrees (-90.0 to 90.0)
        
        Returns:
        - Land timezone name or None for ocean locations
        """

Usage Examples

Basic Instance Usage

from timezonefinder import TimezoneFinder

# Create instance
tf = TimezoneFinder()

# Single lookup
tz = tf.timezone_at(lng=13.358, lat=52.5061)
print(tz)  # 'Europe/Berlin'

# Land timezone only
land_tz = tf.timezone_at_land(lng=0.0, lat=0.0)
print(land_tz)  # None (ocean location)

High-Performance Usage

from timezonefinder import TimezoneFinder

# Load data into memory for faster repeated queries
tf = TimezoneFinder(in_memory=True)

# Check performance capabilities
print(f"Using Numba: {tf.using_numba()}")
print(f"Using C extension: {tf.using_clang_pip()}")

# Batch processing
coordinates = [
    (13.358, 52.5061),    # Berlin
    (-74.0060, 40.7128),  # New York  
    (139.6917, 35.6895)   # Tokyo
]

for lng, lat in coordinates:
    tz = tf.timezone_at(lng=lng, lat=lat)
    print(f"({lat:.3f}, {lng:.3f}) -> {tz}")

Lightweight Approximation

from timezonefinder import TimezoneFinderL

# Fast approximation without polygon checking
tfl = TimezoneFinderL()

# Quick timezone suggestion
tz = tfl.timezone_at(lng=13.358, lat=52.5061)
print(tz)  # 'Europe/Berlin' (most common in area)

Thread-Safe Usage

import threading
from timezonefinder import TimezoneFinder

def worker(coordinates, results, thread_id):
    # Each thread gets its own instance
    tf = TimezoneFinder(in_memory=True)
    
    for i, (lng, lat) in enumerate(coordinates):
        tz = tf.timezone_at(lng=lng, lat=lat)
        results[thread_id][i] = tz

# Prepare data for multiple threads
all_coords = [(lng, lat) for lng in range(-180, 180, 10) 
              for lat in range(-90, 90, 10)]
              
threads = []
results = [{} for _ in range(4)]

# Split work across threads
chunk_size = len(all_coords) // 4
for i in range(4):
    start = i * chunk_size
    end = start + chunk_size if i < 3 else len(all_coords)
    coords_chunk = all_coords[start:end]
    
    thread = threading.Thread(
        target=worker, 
        args=(coords_chunk, results, i)
    )
    threads.append(thread)
    thread.start()

# Wait for completion
for thread in threads:
    thread.join()

Install with Tessl CLI

npx tessl i tessl/pypi-timezonefinder

docs

cli.md

core-lookup.md

geometry.md

global-functions.md

index.md

tile.json