Quick Start

Project tzf provides multiple languages supports to lookup timezone by longitude and latitude.

Language or SeverRepository LinkAPI Doc
Goringsaturn/tzf
RubyHarlemSquirrel/tzf-rb
Rustringsaturn/tzf-rs
Swiftringsaturn/tzf-swift
Pythonringsaturn/tzfpytzfpy.pyi
HTTP APIracemap/rust-tz-service
Redis Serverringsaturn/tzf-server
JS via Wasm(browser only)ringsaturn/tzf-wasm
Onlineringsaturn/tzf-web

Go

1go get github.com/ringsaturn/tzf
 1// Use about 150MB memory for init, and 60MB after GC.
 2package main
 3
 4import (
 5	"fmt"
 6
 7	"github.com/ringsaturn/tzf"
 8)
 9
10func main() {
11	finder, err := tzf.NewDefaultFinder()
12	if err != nil {
13		panic(err)
14	}
15	fmt.Println(finder.GetTimezoneName(116.6386, 40.0786))
16}
Full precise support
 1// Use about 900MB memory for init, and 660MB after GC.
 2package main
 3
 4import (
 5	"fmt"
 6
 7	"github.com/ringsaturn/tzf"
 8	tzfrel "github.com/ringsaturn/tzf-rel"
 9	pb "github.com/ringsaturn/tzf/gen/go/tzf/v1"
10	"google.golang.org/protobuf/proto"
11)
12
13func main() {
14	input := &pb.Timezones{}
15
16	// Full data, about 83.5MB
17	dataFile := tzfrel.FullData
18
19	if err := proto.Unmarshal(dataFile, input); err != nil {
20		panic(err)
21	}
22	finder, _ := tzf.NewFinderFromPB(input)
23	fmt.Println(finder.GetTimezoneName(116.6386, 40.0786))
24}

Rust

1cargo add tzf-rs
 1use lazy_static::lazy_static;
 2use tzf_rs::DefaultFinder;
 3
 4lazy_static! {
 5    static ref FINDER: DefaultFinder = DefaultFinder::new();
 6}
 7
 8fn main() {
 9    // Please note coords are lng-lat.
10    print!("{:?}\n", FINDER.get_tz_name(116.3883, 39.9289));
11    print!("{:?}\n", FINDER.get_tz_names(116.3883, 39.9289));
12}
Full precise support

By default, tzf-rs uses a simplified shape data. If you need 100% accurate lookup, you can use the following code to setup.

  1. Download full data set, about 90MB.
  2. Use the following code to setup.
 1use tzf_rs::Finder;
 2use tzf_rs::gen::tzf::v1::Timezones;
 3
 4pub fn load_full() -> Vec<u8> {
 5    include_bytes!("./combined-with-oceans.bin").to_vec()
 6}
 7
 8fn main() {
 9    println!("Hello, world!");
10    let file_bytes: Vec<u8> = load_full();
11
12    let finder = Finder::from_pb(Timezones::try_from(file_bytes).unwrap_or_default());
13    let tz_name = finder.get_tz_name(139.767125, 35.681236);
14    println!("tz_name: {}", tz_name);
15}

A full example can be found here.

Python

 1# Install just tzfpy
 2pip install tzfpy
 3
 4# Install with pytz
 5pip install "tzfpy[pytz]"
 6
 7# Install with tzdata. https://github.com/python/tzdata
 8pip install "tzfpy[tzdata]"
 9
10# Install via conda, see more in https://github.com/conda-forge/tzfpy-feedstock
11conda install -c conda-forge tzfpy
1>>> from tzfpy import get_tz, get_tzs
2>>> get_tz(116.3883, 39.9289)  # in (longitude, latitude) order.
3'Asia/Shanghai'
4>>> get_tzs(87.4160, 44.0400)  # in (longitude, latitude) order.
5['Asia/Shanghai', 'Asia/Urumqi']

Python version does not support full precise support.

Wasm

 1<!DOCTYPE html>
 2<html lang="en">
 3  <head>
 4    <meta charset="UTF-8" />
 5    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 6    <title>tzf-web Example</title>
 7    <script type="module">
 8      import init, { WasmFinder } from "https://www.unpkg.com/tzf-wasm@v0.1.4/tzf_wasm.js";
 9
10      let finder;
11
12      async function loadWasm() {
13        await init();
14        finder = new WasmFinder();
15        const lng = -74.006;
16        const lat = 40.7128;
17        const timezone = finder.get_tz_name(lng, lat);
18        console.log(`Timezone for (${lat}, ${lng}): ${timezone}`);
19      }
20
21      loadWasm();
22    </script>
23  </head>
24  <body></body>
25</html>

Online preview: http://ringsaturn.github.io/tzf-web/

Swift

Add the dependency to your Package.swift file:

1dependencies: [
2    .package(url: "https://github.com/ringsaturn/tzf-swift.git", from: "{latest_version}")
3]
 1import Foundation
 2import tzf
 3
 4do {
 5    let finder = try DefaultFinder()
 6
 7    // Test for Beijing
 8    let timezone = try finder.getTimezone(lng: 116.3833, lat: 39.9167)
 9    print("Beijing timezone:", timezone)
10
11    // Test for a location with multiple possible timezones
12    let timezones = try finder.getTimezones(lng: 87.5703, lat: 43.8146)
13    print("Multiple possible timezones:", timezones)
14
15    // Get data version
16    print("Data version:", finder.dataVersion())
17
18} catch {
19    print("Error:", error)
20}

Ruby

Ruby version is created and maintained by HarlemSquirrel.

Detailed documentation can be found in it’s repo tzf-rb.

1bundle add tzf
2# or
3gem install tzf
1# https://github.com/HarlemSquirrel/tzf-rb
2require 'tzf'
3
4TZF.tz_name(40.74771675713742, -73.99350390136448)
5# => "America/New_York"
6
7TZF.tz_names(40.74771675713742, -73.99350390136448)
8# => ["America/New_York"]

CLI

There are 2 CLI implementations for project-tzf, one is based on Go, the other is based on Rust.

tzf’s CLI

1go install github.com/ringsaturn/tzf/cmd/tzf@latest

Then:

1tzf -lng 116.3883 -lat 39.9289

Or batch process:

1echo -e "116.3883 39.9289\n116.3883, 39.9289" | tzf -stdin-order lng-lat

tzf-rs’s CLI

1cargo install tzf-rs

Then:

1tzf --lng 116.3883 --lat 39.9289

Or batch process:

1echo -e "116.3883 39.9289\n116.3883, 39.9289" | tzf --stdin-order lng-lat

If you are using NixOS, you can install tzf-rs’s CLI via Nix, please see NixOS for more details, since it’s maintained by community.