TZDB — time zone database

In the previous post I offered some details on the new TTimeZone class in Delphi XE. In Today’s post I will present a new project that is based on TTimeZone and offers support for most known (if not all) time zones in wild.

All the time zone information used by the project is provided by tz database project. This database is used in quite a few systems out there including BSDs, GNU LibC, Java, Oracle, MacOS, Linux and etc.

TZDB is made of three modules:

  1. TZUpdate, a small command line utility that takes as input the path to the tz rule files and generates a pascal source file filled with pre-packed constants.
  2. TZDB, a package that contain only one unit: TimeZones. This unit implements a new class, TBundledTimeZone, derived from TTimeZone. This package is basically all you need.
  3. TZVisualizer, a small VCL project that extracts time zone information from a given time zone. It writes all time intervals in a given year, their offset and etc.

First, I would like to detail a bit more about TimeZones unit. It exports only only class but internally it implements all the required logic required to process time zone information generated by the TZUpdate tool. TZUpdate is normally configured to emit a file (included by TimeZone.pas unit). What this meas is that all this information gets compiled into your application if you are including this unit directly (and increases the application size by about 700Kb right now). But that was one of my choices — allow anyone to copy/paste two files into their project and have the full database at their hands. This is not the recommended way though, as I will explain later on.

Why use TZDB?

Not many people will find this database useful. The normal use cases are for application that actually need to do time conversions between multiple time zones (usually server side). Or maybe you want to implement a “world clock”-like application.

In some cases you might even find it useful as a replacement to the TTimeZone.Local implementation. These cases are related to the fact that Windows will not offer you time zone information for years that passed (in most cases DST rules are different from one year to another) thus making time calculations with past date/times error-prone. TZ database stores all known periods and DST rules that were used in a region, thus you can be sure that any time related calculation is correct for the given year.

Timezone updates

A bitter aspect of using a bundled time zone database is the fact that DST rules change between years. Hopefully not that much, but they do change. Operating system cope with that by issuing updates. In case of a 3rd party application, the vendor should also issue update to its application when some DST rules have change (otherwise you risk having outdated data and rick big date/time problems).

For one, I strongly recommend that applications rely on TTimeZone.Local if they only need local time zone information. TTimeZone.Local uses OS provided information thus is safe when updates intervene.

If you need TZDB in your application, you should rely on packages and specifically – run time packages. This means that you include TZDB as a package that your application relies upon and mark this package as run time. This ensures that the database is external in a BPL and that BPL can be simply replaced within an update to your application.

An example!

  SysUtils, DateUtils, TimeZones;

  LSydneyTZ: TTimeZone;
  LLocal, LUtc,
    LSydneyLocal: TDateTime;

  { Create a new time zone for Sydney, Australia }
  LSydneyTZ := TBundledTimeZone.Create('Australia/Sydney');

  { Get the local time for my region/computer }
  LLocal := Now;

  { Convert this to UTC }
  LUtc := TTimeZone.Local.ToUniversalTime(LLocal);

  { And now convert the UTC to Sydney's local time }
  LSydneyLocal := LSydneyTZ.ToLocalTime(LUtc);

  { Write results }
  WriteLn('Current local time is: ', DateTimeToStr(LLocal));
  WriteLn('Current Sydney time is: ', DateTimeToStr(LSydneyLocal));

  { ... }

Visualizing the time zones

Disclaimer: I am very bad with drawing, be it pen, mouse or code 🙂 That’s why I chose to go with something I can do better: fonts, color and text.

The following picture shows information about the local time zone on my machine (by using TTimeZone.Local):

The application allows visualizing bundled time zones (by selecting one from the combo box):

For now I do not have a package/download for TZDB. But you can checkout it from here. Note that there might be some bugs lurking around, so be careful.