tzif
The tzif library loads TZif v1, v2, and v3 files from the IANA time
zone database into inspectable terms and answers UTC-based lookup
queries over one or more zones.
Requires a backend Prolog compiler with unbounded integer arithmetic.
Current feature set:
Loads sources given as
file(Path, ZoneId),files(Root, Paths),directory(Root),stream(Stream, ZoneId),bytes(Bytes, ZoneId), orsnapshot(File)usingload/1orload/2.Supports TZif v1, v2, and v3, including validated skipping of the v1 compatibility block in v2/v3 files.
Parses POSIX footers, including signed-hour and signed-minute offsets.
Exposes zone-aware lookup predicates over loaded
tzif(...)terms, plus cached convenience variants for zone and single-zone queries.Exposes strict local civil-time lookup predicates that fail cleanly for ambiguous or nonexistent times.
Exposes
*_with_resolutionlocal civil-time query predicates for explicit resolution modes (strict,first,second, andall).Exposes
*_reifiedlocal civil-time query predicates that returnunique(...),ambiguous(...), ornonexistentresults.Caches successful
load/1calls automatically, whileload/2returns a loaded term without changing the cache.Provides
cache/1for making an already loadedtzif(...)term the active cached term.Saves and reloads
tzif(...)terms as plain Prolog snapshot files, withsave/1providing a convenience predicate for saving the cached term.Returns the source term recorded in the active cached term via
cache_source/1.Exposes the active cached term using
cached_tzif/1.Exposes the cached zone list using
zones/1.Accepts UTC queries as Unix seconds or
date_time/6terms.Validates zone identifiers against bundled IANA TZDB 2026a canonical names plus backward-compatible aliases.
API documentation
Open the ../../apis/library_index.html#tzif link in a web browser.
Loading
To load all entities in this library, load the loader.lgt file:
| ?- logtalk_load(tzif(loader)).
Testing
To test this library predicates, load the tester.lgt file:
| ?- logtalk_load(tzif(tester)).
Representation
Loaded sources are returned by load/2 as lists of
tzif(Zone, Source, ZoneData) terms, one term per loaded zone.
Each nested ZoneData term contains the parsed block data,
leap-second records, and parsed footer for a single zone. These per-zone
tzif(...) terms are stable enough to be serialized directly using
save/2 and restored using load(snapshot(File), TZifs).
For directory and file-set loads, zone identifiers are the relative
paths used to locate the TZif files inside the root directory, and each
loaded term records its own file(File, ZoneId) source.
When loading a directory(Root), regular files whose relative paths
are not recognized zone identifiers are ignored. This allows loading
system zoneinfo trees that also contain metadata files such as
leapseconds.
For single-zone file, stream, and byte-list loads, the caller must
provide the zone identifier explicitly using file(Path, ZoneId),
stream(Stream, ZoneId), or bytes(Bytes, ZoneId).
The cache stores one tzif(...) term per zone id. load/1 and
cache/1 replace only cached entries whose zone ids match the newly
loaded terms.
Zone identifier validation
The library validates zone identifiers using bundled data derived from
the official IANA TZDB 2026a release. Accepted identifiers include both
canonical zone names such as America/New_York and
backward-compatible aliases such as US/Eastern.
The bundled data is generated from the IANA zone1970.tab and
backward files and does not consult the host operating system’s
installed zoneinfo tree.
To refresh the bundled table for a newer IANA release, run:
$ ./update_zone_ids.sh 2026a
Local Queries
The library provides three sets of predicates for local civil-time queries.
Strict predicates:
local_time_type/2-4local_offset/2-4local_daylight_saving_time/2-4local_abbreviation/2-4
These predicates are intended for local civil times with a unique interpretation. They fail for ambiguous fold times and nonexistent gap times.
Explicit-resolution predicates:
local_time_type_with_resolution/3-5local_offset_with_resolution/3-5local_daylight_saving_time_with_resolution/3-5local_abbreviation_with_resolution/3-5
These predicates accept an explicit resolution mode argument. Supported
modes are strict, first, second, and all.
strict: succeed only when the local civil time has a unique interpretationfirst: select the earliest valid interpretationsecond: select the latest valid interpretationall: enumerate all valid interpretations in chronological order
Reified predicates:
local_time_type_reified/2-4local_offset_reified/2-4local_daylight_saving_time_reified/2-4local_abbreviation_reified/2-4
These predicates never use failure to distinguish ambiguity from absence. Instead, they return one of the following results:
unique(...)ambiguous(...)nonexistent
Examples
Load a single TZif payload without caching it:
| ?- tzif::load(bytes(Bytes, 'America/New_York'), TZifs).
Cache an already loaded term explicitly:
| ?- tzif::load(bytes(Bytes, 'America/New_York'), TZifs), tzif::cache(TZifs).
Load a directory tree of TZif files:
| ?- tzif::load(directory('/usr/share/zoneinfo'), TZifs).
Query a specific zone in a loaded term:
| ?- tzif::load(bytes(Bytes, 'America/New_York'), [TZif]).
| ?- tzif::offset(TZif, 'America/New_York', date_time(2024, 7, 1, 12, 0, 0), Offset).
Query a specific zone in the cached term:
| ?- tzif::load(directory('/usr/share/zoneinfo')).
| ?- tzif::offset('America/New_York', date_time(2024, 7, 1, 12, 0, 0), Offset).
Persist and reload a snapshot:
| ?- tzif::save(TZifs, 'snapshot.pl').
| ?- tzif::load(snapshot('snapshot.pl'), ReloadedTZifs).
Save the cached terms directly:
| ?- tzif::load(directory('/usr/share/zoneinfo')).
| ?- tzif::save('snapshot.pl').
Load using a backward-compatible alias:
| ?- tzif::load(bytes(Bytes, 'US/Eastern'), TZifs).
Use the automatic cache populated by load/1:
| ?- tzif::load(snapshot('snapshot.pl')).
| ?- tzif::abbreviation(date_time(2024, 7, 1, 12, 0, 0), Abbreviation).
Resolve an ambiguous local civil time explicitly:
| ?- tzif::local_offset_with_resolution('America/New_York', date_time(2024, 11, 3, 1, 30, 0), first, Offset).
Inspect whether a local civil time is unique, ambiguous, or nonexistent:
| ?- tzif::local_time_type_reified('America/New_York', date_time(2024, 11, 3, 1, 30, 0), Result).
List cached zones directly:
| ?- tzif::load(directory('/usr/share/zoneinfo')).
| ?- tzif::zones(Zones).