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.
- π tzbundler: IANA Time Zone Database Parser and Bundler
- ποΈ Table of Contents
- π― Who Should Use tzbundler?
- β¨ Features
- π Quick Start
- π Quick Start - Just Download!
- π Data Model
- π Input Files
- π€ Output Files
- πͺ Windows Timezone Support
- β How to Use the Rules (DST Logic)
- ποΈ File Structure
- π§ͺ Testing
- π‘ Use Cases
- π¦ Installation & Requirements
- βοΈ Important Design Decision
- π‘οΈ Error Handling and Robustness
- π Resources
- π€ Contributing
- π License
- π Acknowledgements
- 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
- 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
python run_tzbundler.pyThis single command will:
- Fetch the latest IANA tzdata
- Download Windows timezone mappings from Unicode CLDR
- Extract and parse all files
- Generate
combined.jsonandcombined.sqlitein thetzdata/folder
Use the pre-generated .json or .sqlite bundle from tzdata/ folder or the Releases page.
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 namesRepresents 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 parsingRepresents 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"
}
]
}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 |
{
"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"
}Four normalized tables:
name(TEXT PRIMARY KEY)country_code(TEXT)latitude(TEXT)longitude(TEXT)comment(TEXT)
zone_name(TEXT)to_utc(TEXT)offset(TEXT)abbr(TEXT)rule_name(TEXT)
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_name(TEXT) - Windows timezone nameiana_name(TEXT) - IANA timezone name
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
# 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"]-- 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);Important:
tzbundler provides raw rule dataβyou must calculate DST status yourself using the rules and transitions.
To determine if DST is active for a specific zone and date (e.g., "Australia/Sydney" on May 23, 2030):
- 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
- If
rule_nameisnullor"-": No DST (fixed offset zone) - Otherwise, get the rule set:
tzdata['rules'][rule_name]
- 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")
- DST start rule:
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
- 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
- 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)
# 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/SQLiteassets/ # 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 setupYou can run all tests in two ways:
With pytest (recommended for CI and automation):
pytest tests/test_tzbundler.pyOr using the provided entry point script:
python run_tests.pyThis will run all major tests (JSON, SQLite, consistency, and structure) and print a summary.
- 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
# Required Python packages
requests>=2.25.0 # For downloading tzdata and Windows mappingsClone and run:
git clone https://github.com/ikelaiah/tzbundler.git
cd tzbundler
pip install -r requirements.txt
python run_tzbundler.pytzbundler 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
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
- IANA Time Zone Database
- tzdata Format Documentation
- tzdata Theory File (Essential for DST implementation)
- Unicode CLDR WindowsZones
Contributions welcome! Please feel free to submit a Pull Request.
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
