Skip to content

FAQ

What is the coordinate order?

All tzf implementations use (longitude, latitude) order — the same as GeoJSON and most geo APIs. Note that some systems (e.g. Google Maps URLs, many geographic textbooks) use (latitude, longitude) instead, so double-check before passing values.

Is tzf 100% accurate?

The default finder is not guaranteed to match the full-precision dataset near timezone boundaries. It applies topology-aware Douglas-Peucker simplification with an epsilon of 0.001 degrees, which limits boundary displacement to roughly 111 m.

Measurements against the full-precision 2026c dataset are documented in BORDER_CHANGE.md:

MetricResult
Certified maximum boundary displacement111.2 m, with 1.0 m tolerance
Boundary length displaced more than 100 m0.41%
Boundary length displaced more than 500 m0%
Total mis-assigned area16,828 km², about 0.003% of Earth
Mis-assigned area within 100 m of the true border92.8%

Only queries within roughly 111 m of a timezone boundary can differ from the full-precision result, and most of the affected band is much narrower.

For 100% accurate lookups, use the full dataset:

  • Go: tzf.NewFullFinder()
  • Rust: enable the full feature (see Getting Started)
  • Python/tzfpy: full-precision mode is not currently supported

How much memory does tzf use?

Initialization cost and runtime cost are not the same number. Building a finder decodes the whole .pb dataset into an intermediate representation, builds the query structures from it, and then drops the intermediate — but freeing memory does not shrink RSS, because the allocator keeps the pages mapped for reuse. So the steady-state data a finder actually retains is several times smaller than the high-water mark reached while loading.

The following figures were measured on an Apple M3 Max in the 2026-07-26 benchmark snapshot.

ImplementationModeInit peakLive
GoFuzzyFinder (preindex only)30.4 MiB2.6 MiB
GoFinder (topology-simplified)127.8 MiB30.0 MiB
GoDefaultFinder (simplified + preindex)124.3 MiB32.3 MiB
GoFullFinder (full-precision + preindex)359.4 MiB155.7 MiB
RustFuzzyFinder (preindex only)23.8 MiB5.1 MiB
RustFinder (topology-simplified)48.0 MiB20.7 MiB
RustDefaultFinder (simplified + preindex)77.0 MiB36.3 MiB
Pythontzfpy DefaultFinder94.8 MiBn/a
  • Init peak is the high-water mark (ru_maxrss) reached while loading. This is what a container memory limit has to accommodate, or the process is killed at startup even though its steady state would have fit.
  • Live is what the finder retains once it is ready to serve queries, from language-native accounting (Go HeapAlloc after a forced GC, Rust a counting global allocator). It is n/a for Python, whose candidates keep their data outside the Python heap.

Size the container for the init peak, but expect the long-running cost to be the live figure. Actual usage varies by platform, allocator, and dataset version.

Why is initialization slow?

The first call to NewDefaultFinder() / DefaultFinder::new() loads and parses the binary timezone data. This is a one-time cost — subsequent lookups are very fast. Always initialize once and reuse the instance. See the language-specific guides for patterns using global variables or lazy_static.

How often is the timezone data updated?

tzf tracks IANA timezone database releases viaevansiroky/timezone-boundary-builder. Processed data is published in ringsaturn/tzf-rel. Library releases follow within a short time of each upstream data release.

What is the difference between Finder, FuzzyFinder, and DefaultFinder?

ClassData usedCoverageSpeed
FuzzyFinderTile preindex onlyInterior tiles only — no result for border/uncovered areasFastest
FinderPolygon dataFull global coverageFast
DefaultFinderTile preindex + polygonFull global coverageFast

FuzzyFinder preindex stores only tiles that lie entirely within a single timezone polygon. When a query point lands in a covered tile it returns the correct timezone immediately. When it does not — near borders, coastlines, or sparse regions — it returns nothing rather than guessing. It is not “approximate”: results are accurate, but coverage is incomplete.

DefaultFinder (recommended) tries the tile preindex first; if no result is found it falls back to full polygon lookup. This gives near-constant speed for the majority of world-city queries while remaining correct for all coordinates.

What license does tzf use?

Code is MIT licensed. Timezone data (distributed via tzf-rel) is ODbL, the same as upstream evansiroky/timezone-boundary-builder.

Additionally, tzf, tzf-rs, and tzfpy carry an “Anti CSDN License” rider that prohibits use on the CSDN platform; this has no effect on other use cases.

See Licenses for details.

Last updated on