Skip to content

ikelaiah/tzbundler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

22 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🌏 tzbundler: IANA Time Zone Database Parser and Bundler

Version Python License: MIT IANA tzdata

tzbundler logo

Version: 1.0.1

A Python tool that parses IANA tzdata files and converts them into machine-readable formats (JSON and SQLite). Perfect for applications, research, or data analysis involving time zones. Includes Windows timezone mappings for cross-platform compatibility.

Or you can simply use the pre-generated bundle from tzdata/ folder or the Releases page.

πŸ—‚οΈ Table of Contents

🎯 Who Should Use tzbundler?

  • App developers who need reliable time zone handling
  • Researchers working on temporal/historical datasets
  • Anyone who wants a cross-language-compatible tzdata format
  • Developers needing Windows timezone compatibility

✨ Features

  • Simple one-command operation: Just run python make_tz_bundle.py
  • Multiple output formats: JSON and SQLite database
  • Complete data extraction: Zones, transitions, rules, and aliases
  • Windows timezone support: Official Windows timezone mappings from Unicode CLDR
  • Rich metadata: Country codes, coordinates, and comments
  • Version tracking: Automatically includes tzdata version info
  • Consumer-driven DST logic: Raw rule data provided for flexible DST calculations

πŸš€ Quick Start

python run_tzbundler.py

This single command will:

  1. Fetch the latest IANA tzdata
  2. Download Windows timezone mappings from Unicode CLDR
  3. Extract and parse all files
  4. Generate combined.json and combined.sqlite in the tzdata/ folder

πŸš€ Quick Start - Just Download!

Use the pre-generated .json or .sqlite bundle from tzdata/ folder or the Releases page.

πŸ“Š Data Model

Zone

Represents a time zone with its complete history and metadata.

@dataclass
class Zone:
    name: str                       # e.g., "Asia/Seoul"
    country_code: str               # e.g., "KR" 
    latitude: str                   # from coordinates
    longitude: str                  # from coordinates  
    comment: str                    # optional description
    transitions: List[Transition]   # historical transitions
    aliases: List[str]              # alternative names
    win_names: List[str]            # Windows timezone names

πŸ”„ Transition

Represents a period in a zone's history (offset changes, DST periods, etc.).

Note: DST status is not pre-calculated. Consumers should use the rules data to determine DST as needed.

@dataclass  
class Transition:
    to_utc: Optional[str]      # when this period ends (IANA UNTIL; empty string if ongoing)
    offset: str                # UTC offset (e.g., "+09:00")
    abbr: str                  # abbreviation (e.g., "KST", "JST")
    # rule_name: Optional[str] # attached as attribute during parsing

πŸ“ Rule

Represents a single DST rule definition (from a Rule line in tzdata).

"rules": {
  "Japan": [
    {
      "from": "1948",
      "to": "only",
      "type": "-",
      "in": "Sep",
      "on": "10",
      "at": "0:00",
      "save": "1:00",
      "letter": "D"
    }
  ]
}

πŸ“ Input Files

The tool processes these IANA tzdata files:

File Category Files Contains
Zone Data africa, antarctica, asia, australasia, europe, northamerica, southamerica Zone blocks, Rule lines, Link lines
Additional etcetera, backward, backzone Extra zones and compatibility aliases
Metadata zone1970.tab Country codes, coordinates, comments
Version version tzdata release version
Windows Mappings windowsZones.xml Windows-IANA timezone mappings from Unicode CLDR

πŸ“€ Output Files

πŸ“ JSON Format (combined.json)

{
  "timezones": {
    "Asia/Seoul": {
      "country_code": "KR",
      "coordinates": "+3733+12658", 
      "comment": "",
      "transitions": [
        {
          "to_utc": "1948 May 8",
          "offset": "+08:30",
          "abbr": "KST",
          "rule_name": null
        },
        {
          "to_utc": "",
          "offset": "+09:00",
          "abbr": "KDT",
          "rule_name": "Korea"
        }
      ],
      "aliases": ["ROK"],
      "win_names": ["Korea Standard Time"]
    }
  },
  "rules": {
    "Korea": [
      {
        "from": "1948",
        "to": "only",
        "type": "-",
        "in": "May",
        "on": "8",
        "at": "0:00",
        "save": "1:00",
        "letter": "D"
      }
    ]
  },
  "windows_mapping": {
    "Korea Standard Time": ["Asia/Seoul"]
  },
  "_version": "2025b"
}

πŸ’Ύ SQLite Database (combined.sqlite)

Four normalized tables:

zones

  • name (TEXT PRIMARY KEY)
  • country_code (TEXT)
  • latitude (TEXT)
  • longitude (TEXT)
  • comment (TEXT)

transitions

  • zone_name (TEXT)
  • to_utc (TEXT)
  • offset (TEXT)
  • abbr (TEXT)
  • rule_name (TEXT)

rules

  • rule_name (TEXT)
  • from_year (TEXT)
  • to_year (TEXT)
  • type (TEXT)
  • in_month (TEXT)
  • on_day (TEXT)
  • at_time (TEXT)
  • save (TEXT)
  • letter (TEXT)

windows_mapping

  • windows_name (TEXT) - Windows timezone name
  • iana_name (TEXT) - IANA timezone name

πŸͺŸ Windows Timezone Support

tzbundler includes official Windows timezone mappings from the Unicode CLDR project:

  • Bidirectional mappings: IANA ↔ Windows timezone names
  • Authoritative source: Uses the official Unicode CLDR windowsZones.xml
  • Cross-platform compatibility: Perfect for applications that need to work with both IANA and Windows timezones

Example Usage

# Find Windows name for IANA timezone
asia_seoul_windows = timezones["Asia/Seoul"]["win_names"]  # ["Korea Standard Time"]

# Find IANA zones for Windows timezone
korea_iana_zones = windows_mapping["Korea Standard Time"]  # ["Asia/Seoul"]

SQL Query Examples for Windows Mappings

-- Find Windows timezone name for an IANA zone
SELECT z.name, wm.windows_name 
FROM zones z 
JOIN windows_mapping wm ON z.name = wm.iana_name 
WHERE z.name = 'Asia/Seoul';

-- List all Windows timezones and their IANA equivalents
SELECT windows_name, GROUP_CONCAT(iana_name, ', ') as iana_zones
FROM windows_mapping 
GROUP BY windows_name;

-- Find zones that have Windows mappings
SELECT z.name, z.country_code 
FROM zones z 
WHERE EXISTS (SELECT 1 FROM windows_mapping wm WHERE wm.iana_name = z.name);

❓ How to Use the Rules (DST Logic)

Important:
tzbundler provides raw rule dataβ€”you must calculate DST status yourself using the rules and transitions.

How to Determine DST Status for a Date

To determine if DST is active for a specific zone and date (e.g., "Australia/Sydney" on May 23, 2030):

Step 1: Find the Active Transition

  • Get the current transition for your zone (usually the last one in the transitions array)
  • This gives you the base UTC offset and rule name

Step 2: Check for DST Rules

  • If rule_name is null or "-": No DST (fixed offset zone)
  • Otherwise, get the rule set: tzdata['rules'][rule_name]

Step 3: Find Applicable Rules for Your Year

  • Look for rules where: from_year <= target_year <= to_year
  • You'll typically find two types:
    • DST start rule: save > 0 (e.g., "1:00")
    • DST end rule: save = 0 (e.g., "0")

Step 4: Calculate Rule Dates

Parse the IANA date specifications:

  • "lastSun" = Last Sunday of the month
  • "Sun>=8" = First Sunday on or after the 8th
  • "15" = 15th day of the month

Step 5: Apply Hemisphere Logic

  • Northern Hemisphere (US/Europe): DST typically Mar-Nov
    • DST active = start_date <= target_date < end_date
  • Southern Hemisphere (Australia): DST typically Oct-Apr
    • DST active = target_date >= start_date OR target_date < end_date

Step 6: Handle Edge Cases

  • Ambiguous times: When clocks "fall back", some times occur twice
  • Invalid times: When clocks "spring forward", some times don't exist
  • Time suffixes: s=standard, u/g/z=UTC, w=wall (default)

Example: Australia/Sydney on May 23, 2030

# 1. Active transition
transition = tzdata['timezones']['Australia/Sydney']['transitions'][-1]
# Result: offset="+10:00", rule_name="AN"

# 2. Get DST rules
an_rules = tzdata['rules']['AN']

# 3. Find 2030 rules
current_rules = [r for r in an_rules if r['from'] <= '2030' <= r.get('to', '9999')]
# DST ends: Apr Sun>=1 (April 7, 2030)  
# DST starts: Oct Sun>=1 (October 6, 2030)

# 4. Check date
test_date = May 23, 2030
# May 23 is AFTER April 7 (DST end) and BEFORE October 6 (DST start)
# Therefore: DST is NOT active

# 5. Result
is_dst = False
offset = "+10:00"  # Base offset only
abbreviation = "AEST"  # AE%sT with %s="S" for Standard


## πŸ• How to Calculate DST Status (Detailed)

See [How to Calculate DST Status](docs/how-to-calculate-dst-status.md)

## ❓ How Parsing Works (Detailed)

See [How Parsing Works](docs/how-parsing-works.md)

### Data Processing Flow

```txt
Raw tzdata files β†’ Parse zones/rules/links β†’ Enrich with metadata β†’ Add Windows mappings β†’ Output JSON/SQLite

πŸ—„οΈ File Structure

assets/                 # Project assets (e.g., logos)
docs/                   # Documentation
example/                # Example data and usage
tests/                  # Unified and supporting test scripts
β”œβ”€β”€ test_tzbundler.py   # Unified test suite for all outputs
└── test_windowsZones.py
tzbundler/              # Main package source code
β”œβ”€β”€ __init__.py
β”œβ”€β”€ get_latest_tz.py
└── make_tz_bundle.py
tzdata/                 # Processed output
β”œβ”€β”€ combined.json
└── combined.sqlite
tzdata_raw/             # Downloaded raw IANA and CLDR files
CHANGELOG.md            # Release notes
CONTRIBUTING.md         # Contribution guidelines
LICENSE                 # License file
README.md               # Project documentation
requirements.txt        # Python dependencies
run_tests.py            # Entry point to run all tests
run_tzbundler.py        # Main script to generate tzdata bundles
setup.py                # Package setup

πŸ§ͺ Testing

You can run all tests in two ways:

With pytest (recommended for CI and automation):

pytest tests/test_tzbundler.py

Or using the provided entry point script:

python run_tests.py

This will run all major tests (JSON, SQLite, consistency, and structure) and print a summary.

πŸ’‘ Use Cases

  • Cross-Platform Applications: Handle both IANA and Windows timezone identifiers
  • Data Analysis: Research time zone changes and patterns
  • Historical Analysis: Track offset changes over time
  • Compliance: Ensure accurate time zone handling
  • Custom DST Logic: Implement domain-specific DST calculations
  • Migration Projects: Convert between Windows and IANA timezone systems

πŸ“¦ Installation & Requirements

# Required Python packages
requests>=2.25.0    # For downloading tzdata and Windows mappings

Clone and run:

git clone https://github.com/ikelaiah/tzbundler.git
cd tzbundler
pip install -r requirements.txt
python run_tzbundler.py

βš™οΈ Important Design Decision

tzbundler does not pre-calculate DST status. Instead, it provides:

  • βœ… Raw transition data (offsets, dates, abbreviations)
  • βœ… Complete DST rule definitions
  • βœ… Rule names linked to transitions
  • βœ… Windows timezone mappings
  • ❌ Pre-calculated DST boolean flags

Why? This design:

  • Avoids bundler bugs affecting DST calculations
  • Allows consumers to implement DST logic that fits their needs
  • Enables caching and on-demand DST computation
  • Keeps complex temporal logic out of the data extraction layer
  • Provides maximum flexibility for cross-platform compatibility

πŸ›‘οΈ Error Handling and Robustness

The tool includes comprehensive error handling:

  • Network issues: Gracefully handles connection failures and provides troubleshooting tips
  • File corruption: Validates downloaded archives and provides cleanup on failure
  • Parsing errors: Logs problematic lines but continues processing
  • Missing files: Warns about missing files but continues with available data
  • Partial downloads: Detects and handles incomplete downloads

πŸ”— Resources

🀝 Contributing

Contributions welcome! Please feel free to submit a Pull Request.

πŸ“ License

MIT License

πŸ™ Acknowledgements

Special thanks to the Python core developers and the wider Python community for building and maintaining the language and ecosystem that make projects like this possible.

Special thanks to a-blekot for valuable feedback and suggestions on naming and IANA compatibility.


Built with ❀️ for developers who need reliable timezone data

About

🌍 Parse IANA timezone database into JSON & SQLite with Windows timezone support. Includes DST rules, historical transitions, and comprehensive metadata for timezone-aware applications.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages