CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-python-dateutil

Extensions to the standard Python datetime module

Pending
Overview
Eval results
Files

zoneinfo.mddocs/

Timezone Database Access

Access to dateutil's bundled timezone database with metadata support, providing an alternative to system timezone data. Includes both modern and deprecated interfaces.

Capabilities

ZoneInfoFile Class

class ZoneInfoFile:
    def __init__(self, zonefile_stream=None):
        """
        Interface to timezone database from tarball stream.
        
        Parameters:
        - zonefile_stream (file-like, optional): Stream containing zoneinfo tarball data
                                               If None, creates empty ZoneInfoFile
        """
        
    def get(self, name, default=None):
        """
        Get timezone by name from the database.
        
        Parameters:
        - name (str): IANA timezone name (e.g., 'America/New_York')
        - default: Value to return if timezone not found
        
        Returns:
        tzfile | default: Timezone object or default value
        """
        
    # Attributes
    zones: dict[str, tzfile]    # Dictionary mapping timezone names to tzfile objects
    metadata: dict | None       # Database metadata (version, build info, etc.)

Usage Examples:

from dateutil.zoneinfo import ZoneInfoFile, get_zonefile_instance
from datetime import datetime

# Use the default instance (recommended)
zif = get_zonefile_instance()

# Get specific timezone
ny_tz = zif.get('America/New_York')
if ny_tz:
    dt = datetime(2023, 12, 25, 12, 0, tzinfo=ny_tz)
    print(f"Time in NY: {dt}")

# Handle missing timezone gracefully
unknown_tz = zif.get('Invalid/Timezone', default=None)
if unknown_tz is None:
    print("Timezone not found")

# Explore available timezones
print(f"Available timezones: {len(zif.zones)}")
print(f"Sample timezones: {list(zif.zones.keys())[:10]}")

# Check metadata
if zif.metadata:
    print(f"Database version: {zif.metadata.get('version', 'unknown')}")

Timezone Database Instance Management

def get_zonefile_instance(new_instance=False):
    """
    Get cached or new ZoneInfoFile instance using dateutil's bundled data.
    
    Parameters:
    - new_instance (bool): If True, create and cache new instance
                          If False, return existing cached instance
    
    Returns:
    ZoneInfoFile: Timezone database instance
    """

Usage Examples:

from dateutil.zoneinfo import get_zonefile_instance

# Get default cached instance (efficient for repeated use)
zif1 = get_zonefile_instance()
zif2 = get_zonefile_instance()
print(f"Same instance: {zif1 is zif2}")  # True

# Force new instance creation
zif_new = get_zonefile_instance(new_instance=True)
print(f"New instance: {zif1 is zif_new}")  # False

# Subsequent calls return the new cached instance
zif3 = get_zonefile_instance()
print(f"Uses new cache: {zif3 is zif_new}")  # True

Internal Database Access

def getzoneinfofile_stream():
    """
    Get the raw zoneinfo tarball data as a stream.
    
    Returns:
    BytesIO | None: Stream containing dateutil's bundled zoneinfo tarball data,
                   or None if file cannot be read
    
    Warning:
    Internal function - prefer using get_zonefile_instance() for normal usage
    """

Usage Examples:

from dateutil.zoneinfo import getzoneinfofile_stream, ZoneInfoFile

# Get raw zoneinfo stream (advanced usage)
stream = getzoneinfofile_stream()
if stream:
    # Create custom ZoneInfoFile instance
    custom_zif = ZoneInfoFile(stream)
    print(f"Loaded {len(custom_zif.zones)} timezones")
else:
    print("Could not access zoneinfo data")

Custom ZoneInfo Loading

from dateutil.zoneinfo import ZoneInfoFile
from io import BytesIO

# Load from custom tarball data (advanced usage)
with open('custom-zoneinfo.tar.gz', 'rb') as f:
    custom_zif = ZoneInfoFile(f)
    
    # Use custom timezone data
    custom_tz = custom_zif.get('Custom/Timezone')
    print(f"Custom zones available: {len(custom_zif.zones)}")

Deprecated Interface

Warning: The following functions are deprecated as of dateutil 2.6 and will be removed in future versions. Use ZoneInfoFile class instead.

Deprecated Functions

def gettz(name):
    """
    Get timezone from dateutil's bundled zoneinfo tarball.
    
    DEPRECATED: Use get_zonefile_instance().get(name) instead.
    
    Parameters:
    - name (str): IANA timezone name
    
    Returns:
    tzfile | None: Timezone object or None if not found
    
    Warnings:
    DeprecationWarning: This function will be removed in future versions
    """

def gettz_db_metadata():
    """
    Get zoneinfo database metadata.
    
    DEPRECATED: Use get_zonefile_instance().metadata instead.
    
    Returns:
    dict | None: Database metadata dictionary
    
    Warnings:
    DeprecationWarning: This function will be removed in future versions
    """

Migration Examples:

# OLD (deprecated) - will show deprecation warnings
from dateutil.zoneinfo import gettz, gettz_db_metadata

old_tz = gettz('America/New_York')  # DeprecationWarning
old_metadata = gettz_db_metadata()  # DeprecationWarning

# NEW (recommended) - no warnings
from dateutil.zoneinfo import get_zonefile_instance

zif = get_zonefile_instance()
new_tz = zif.get('America/New_York')
new_metadata = zif.metadata

Advanced Usage Patterns

Timezone Database Exploration

from dateutil.zoneinfo import get_zonefile_instance
import json

def explore_timezone_database():
    """Explore the contents of the timezone database."""
    zif = get_zonefile_instance()
    
    # Basic statistics
    total_zones = len(zif.zones)
    print(f"Total timezone entries: {total_zones}")
    
    # Group by continent
    continents = {}
    for zone_name in zif.zones.keys():
        if '/' in zone_name:
            continent = zone_name.split('/')[0]
            continents[continent] = continents.get(continent, 0) + 1
    
    print("\nTimezones by continent:")
    for continent, count in sorted(continents.items()):
        print(f"  {continent}: {count}")
    
    # Show metadata
    if zif.metadata:
        print(f"\nDatabase metadata:")
        print(json.dumps(zif.metadata, indent=2))
    
    return {
        'total_zones': total_zones,
        'continents': continents,
        'metadata': zif.metadata
    }

# Run exploration
db_info = explore_timezone_database()

Timezone Validation

from dateutil.zoneinfo import get_zonefile_instance
from dateutil.tz import gettz

def validate_timezone_name(tz_name):
    """
    Validate timezone name against multiple sources.
    
    Returns dict with validation results from different sources.
    """
    results = {
        'system_tz': None,
        'dateutil_bundled': None,
        'is_valid': False
    }
    
    # Check system timezone
    system_tz = gettz(tz_name)
    results['system_tz'] = system_tz is not None
    
    # Check dateutil bundled data
    zif = get_zonefile_instance()
    bundled_tz = zif.get(tz_name)
    results['dateutil_bundled'] = bundled_tz is not None
    
    # Overall validity
    results['is_valid'] = results['system_tz'] or results['dateutil_bundled']
    
    return results

# Test various timezone names
test_timezones = [
    'America/New_York',
    'Europe/London',
    'Invalid/Timezone',
    'UTC',
    'US/Eastern'  # Legacy name
]

for tz_name in test_timezones:
    validation = validate_timezone_name(tz_name)
    print(f"{tz_name}: {validation}")

Performance Comparison

from dateutil.zoneinfo import get_zonefile_instance, gettz
from dateutil.tz import gettz as tz_gettz
import time

def benchmark_timezone_access():
    """Compare performance of different timezone access methods."""
    timezone_names = [
        'America/New_York', 'Europe/London', 'Asia/Tokyo',
        'America/Los_Angeles', 'Europe/Paris', 'Asia/Shanghai'
    ]
    
    # Benchmark system gettz
    start = time.time()
    for name in timezone_names * 100:
        tz = tz_gettz(name)
    system_time = time.time() - start
    
    # Benchmark ZoneInfoFile (single instance)
    zif = get_zonefile_instance()
    start = time.time()
    for name in timezone_names * 100:
        tz = zif.get(name)
    bundled_time = time.time() - start
    
    # Benchmark deprecated gettz (with warnings suppressed)
    import warnings
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        start = time.time()
        for name in timezone_names * 100:
            tz = gettz(name)  # Deprecated function
        deprecated_time = time.time() - start
    
    print("Timezone access performance (600 lookups):")
    print(f"System gettz(): {system_time:.4f}s")
    print(f"ZoneInfoFile.get(): {bundled_time:.4f}s")
    print(f"Deprecated gettz(): {deprecated_time:.4f}s")

benchmark_timezone_access()

Database Comparison Tool

from dateutil.zoneinfo import get_zonefile_instance
from dateutil.tz import gettz
from datetime import datetime

def compare_timezone_implementations(tz_name, test_datetime):
    """Compare system vs bundled timezone implementations."""
    
    # Get timezone from both sources
    system_tz = gettz(tz_name)
    
    zif = get_zonefile_instance()
    bundled_tz = zif.get(tz_name)
    
    if not system_tz or not bundled_tz:
        return f"Timezone {tz_name} not available in one or both sources"
    
    # Create datetime with each timezone
    system_dt = test_datetime.replace(tzinfo=system_tz)
    bundled_dt = test_datetime.replace(tzinfo=bundled_tz)
    
    # Compare properties
    comparison = {
        'timezone_name': tz_name,
        'test_datetime': test_datetime,
        'system': {
            'utc_offset': system_tz.utcoffset(test_datetime),
            'dst_offset': system_tz.dst(test_datetime),
            'tzname': system_tz.tzname(test_datetime)
        },
        'bundled': {
            'utc_offset': bundled_tz.utcoffset(test_datetime),
            'dst_offset': bundled_tz.dst(test_datetime), 
            'tzname': bundled_tz.tzname(test_datetime)
        }
    }
    
    # Check for differences
    comparison['differences'] = []
    for prop in ['utc_offset', 'dst_offset', 'tzname']:
        if comparison['system'][prop] != comparison['bundled'][prop]:
            comparison['differences'].append(prop)
    
    return comparison

# Test with specific datetime
test_dt = datetime(2023, 7, 15, 12, 0)  # Summer time
result = compare_timezone_implementations('America/New_York', test_dt)
print(f"Comparison results: {result}")

Constants

ZONEFILENAME = "dateutil-zoneinfo.tar.gz"    # Default zoneinfo tarball filename
METADATA_FN = 'METADATA'                     # Metadata filename within tarball

Types

from dateutil.tz import tzfile
from typing import BinaryIO

class ZoneInfoFile:
    zones: dict[str, tzfile]
    metadata: dict | None
    
    def get(self, name: str, default=None) -> tzfile | None: ...

# Function return types
ZoneInfoInstance = ZoneInfoFile
TzFileResult = tzfile | None
MetadataResult = dict | None

# File stream types for custom loading
ZoneInfoStream = BinaryIO | None

Install with Tessl CLI

npx tessl i tessl/pypi-python-dateutil

docs

easter.md

index.md

parser.md

relativedelta.md

rrule.md

tz.md

utils.md

zoneinfo.md

tile.json