TZDB - IANA Time Zone Database for Delphi/FreePascal

May 1, 2026 · View on GitHub

GNU/Linux macOS Windows (FPC) TZDB/CLDR Bump

Table of Contents

Introduction

TZDB is an offline, in-process compiled database for IANA's TZDB project. It provides reliable time zone conversion and calculation capabilities without requiring external services or runtime dependencies.

The current version is compiled with 2026b version of IANA TZDB and the latest Windows alias translation table (from CLDR project).

The source code is compatible with Delphi XE+ and FreePascal 3+, though some components are only available for Delphi.

📚 API Documentation | 💻 Code Examples

Features

  • Offline operation: No network dependencies or external services required
  • Small footprint: Single-file implementation with pre-compiled TZDB database
  • Windows alias support: Easily convert between Windows time zone names and IANA identifiers
  • Comprehensive API: Rich set of methods for time zone conversions and calculations
  • Pure Pascal implementation: No external dependencies or DLLs

Installation

Option 1: Direct inclusion (simplest)

Download TZDB.pas and add it to your project.

Option 2: Git submodule

git submodule add https://github.com/pavkam/tzdb.git

Usage

Simply include the TZDB unit in your uses clause:

uses TZDB;

Common Examples

Get a time zone and convert local time to UTC

uses TZDB;

var
  LTimeZone: TBundledTimeZone;
begin
  // Get time zone by IANA identifier
  LTimeZone := TBundledTimeZone.GetTimeZone('Africa/Cairo');

  // Convert local time to UTC
  WriteLn(LTimeZone.ToUniversalTime(Now));
end;

Using Windows time zone names

uses TZDB;

var
  LTimeZone: TBundledTimeZone;
begin
  // Get time zone by Windows identifier
  LTimeZone := TBundledTimeZone.GetTimeZone('Eastern Standard Time');

  // Display information
  WriteLn('IANA ID: ', LTimeZone.ID);
  WriteLn('Current offset: ', LTimeZone.UtcOffset);
end;

Check for ambiguous or invalid times

uses TZDB;

var
  LTimeZone: TBundledTimeZone;
  LLocalTime: TDateTime;
  LTimeType: TLocalTimeType;
begin
  LTimeZone := TBundledTimeZone.GetTimeZone('America/New_York');
  LLocalTime := EncodeDate(2023, 11, 5) + EncodeTime(1, 30, 0, 0); // Fall DST transition

  // Check what type of local time this is
  LTimeType := LTimeZone.GetLocalTimeType(LLocalTime);

  case LTimeType of
    lttInvalid: WriteLn('This time does not exist (skipped during DST start)');
    lttAmbiguous: WriteLn('This time is ambiguous (occurs twice during DST end)');
    lttStandard: WriteLn('This is a standard time');
    lttDaylight: WriteLn('This is a daylight saving time');
  end;
end;

Important Considerations

IssueDescriptionHandling
Invalid IDsUnknown time zone IDs cause exceptionsTBundledTimeZone.Create throws ETimeZoneInvalid
Year rangeThe database covers a limited year rangeMethods may throw EUnknownTimeZoneYear for dates outside coverage
Ambiguous timesDuring DST→Standard transitions, some hours occur twiceUse AForceDaylight parameter to control interpretation
Invalid timesDuring Standard→DST transitions, some hours are skippedHandle ELocalTimeInvalid exceptions or check with GetLocalTimeType
Daylight supportNot all time zones have daylight saving timeUse HasDaylightTime to check before DST operations
Multiple periodsSome zones have multiple DST periods in a yearDon't assume a single daylight/standard transition per year
Dynamic propertiesDisplay names and offsets change throughout the yearDon't rely on DisplayName, Abbreviation, or UtcOffset as constants

Updating TZDB

Automatic Updates

This project follows IANA releases closely, typically with a 1-2 week delay.

Manual Updates

To update manually:

  1. Use the update-compile.sh script
  2. Run under MacOS, Linux, or Windows WSL
  3. Requires Free Pascal compiler

Tools

Time Zone Visualizer

A development tool to display time zone details (Windows only):

Screen shot

License

This project is available under MIT License.