{"id":13616364,"url":"https://github.com/ringsaturn/tzf","last_synced_at":"2026-03-08T09:01:07.705Z","repository":{"id":39629014,"uuid":"492206936","full_name":"ringsaturn/tzf","owner":"ringsaturn","description":"Get timezone via longitude and latitude in Go in a fast way","archived":false,"fork":false,"pushed_at":"2025-04-01T10:03:44.000Z","size":1818,"stargazers_count":94,"open_issues_count":1,"forks_count":10,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-02T23:36:14.682Z","etag":null,"topics":["golang","latitude","location","longitude","python","timezone","timezone-library","timezone-picker","tzf"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/ringsaturn/tzf","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ringsaturn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"polar":null,"custom":["https://redcross.org.ua/en/donate/"]}},"created_at":"2022-05-14T12:15:20.000Z","updated_at":"2025-04-01T10:03:41.000Z","dependencies_parsed_at":"2023-11-06T08:29:17.305Z","dependency_job_id":"9c7083df-2b75-47ee-bf33-978804996377","html_url":"https://github.com/ringsaturn/tzf","commit_stats":null,"previous_names":[],"tags_count":48,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ringsaturn%2Ftzf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ringsaturn%2Ftzf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ringsaturn%2Ftzf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ringsaturn%2Ftzf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ringsaturn","download_url":"https://codeload.github.com/ringsaturn/tzf/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247393566,"owners_count":20931812,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["golang","latitude","location","longitude","python","timezone","timezone-library","timezone-picker","tzf"],"created_at":"2024-08-01T20:01:27.530Z","updated_at":"2026-03-08T09:01:07.700Z","avatar_url":"https://github.com/ringsaturn.png","language":"Go","funding_links":["https://redcross.org.ua/en/donate/"],"categories":["Go"],"sub_categories":[],"readme":"# TZF: a fast timezone finder for Go. [![Go Reference](https://pkg.go.dev/badge/github.com/ringsaturn/tzf.svg)](https://pkg.go.dev/github.com/ringsaturn/tzf) [![codecov](https://codecov.io/gh/ringsaturn/tzf/branch/main/graph/badge.svg?token=9KIU85IERM)](https://codecov.io/gh/ringsaturn/tzf)\n\n![](https://github.com/ringsaturn/tzf/blob/gh-pages/docs/tzf-social-media.png?raw=true)\n\nTZF is a fast timezone finder package designed for Go. It allows you to quickly\nfind the timezone for a given latitude and longitude, making it ideal for geo\nqueries and services such as weather forecast APIs. With optimized performance\nand two different data options, TZF is a powerful tool for any Go developer's\ntoolkit.\n\n---\n\n\u003e [!NOTE]\n\u003e\n\u003e Here are some language or server which built with tzf or it's other language\n\u003e bindings:\n\n| Language or Sever         | Link                                                                    | Note                |\n| ------------------------- | ----------------------------------------------------------------------- | ------------------- |\n| Go                        | [`ringsaturn/tzf`](https://github.com/ringsaturn/tzf)                   |                     |\n| Ruby                      | [`HarlemSquirrel/tzf-rb`](https://github.com/HarlemSquirrel/tzf-rb)     | build with tzf-rs   |\n| Rust                      | [`ringsaturn/tzf-rs`](https://github.com/ringsaturn/tzf-rs)             |                     |\n| Swift                     | [`ringsaturn/tzf-swift`](https://github.com/ringsaturn/tzf-swift)       |                     |\n| Python                    | [`ringsaturn/tzfpy`](https://github.com/ringsaturn/tzfpy)               | build with tzf-rs   |\n| HTTP API                  | [`ringsaturn/tzf-server`](https://github.com/ringsaturn/tzf-server)     | build with tzf      |\n| HTTP API                  | [`racemap/rust-tz-service`](https://github.com/racemap/rust-tz-service) | build with tzf-rs   |\n| Redis Server              | [`ringsaturn/tzf-server`](https://github.com/ringsaturn/tzf-server)     | build with tzf      |\n| Redis Server              | [`ringsaturn/redizone`](https://github.com/ringsaturn/redizone)         | build with tzf-rs   |\n| JS via Wasm(browser only) | [`ringsaturn/tzf-wasm`](https://github.com/ringsaturn/tzf-wasm)         | build with tzf-rs   |\n| Online                    | [`ringsaturn/tzf-web`](https://github.com/ringsaturn/tzf-web)           | build with tzf-wasm |\n\n## Quick Start\n\nTo start using TZF in your Go project, you first need to install the package:\n\n```bash\ngo get github.com/ringsaturn/tzf\n```\n\nThen, you can use the following code to locate:\n\n```go\n// Use about 150MB memory for init, and 60MB after GC.\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/ringsaturn/tzf\"\n)\n\nfunc main() {\n\tfinder, err := tzf.NewDefaultFinder()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Println(finder.GetTimezoneName(116.6386, 40.0786))  // In longitude-latitude order\n}\n```\n\nIf you require a query result that is 100% accurate, use the following to\nlocate:\n\n```go\n// Use about 900MB memory for init, and 660MB after GC.\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/ringsaturn/tzf\"\n\ttzfrel \"github.com/ringsaturn/tzf-rel\"\n\tpb \"github.com/ringsaturn/tzf/gen/go/tzf/v1\"\n\t\"google.golang.org/protobuf/proto\"\n)\n\nfunc main() {\n\tinput := \u0026pb.Timezones{}\n\n\t// Full data, about 83.5MB\n\tdataFile := tzfrel.FullData\n\n\tif err := proto.Unmarshal(dataFile, input); err != nil {\n\t\tpanic(err)\n\t}\n\tfinder, _ := tzf.NewFinderFromPB(input)\n\tfmt.Println(finder.GetTimezoneName(116.6386, 40.0786))  // In longitude-latitude order\n}\n```\n\n### Best Practice\n\nIt's expensive to init tzf's Finder/FuzzyFinder/DefaultFinder, please consider\nreuse it or as a global var. Below is a global var example:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/ringsaturn/tzf\"\n)\n\nvar f tzf.F\n\nfunc init() {\n\tvar err error\n\tf, err = tzf.NewDefaultFinder()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n\nfunc main() {\n\t// In longitude-latitude order\n\tfmt.Println(f.GetTimezoneName(116.3883, 39.9289))\n\tfmt.Println(f.GetTimezoneName(-73.935242, 40.730610))\n}\n```\n\n## CLI Tool\n\nIn addition to using TZF as a library in your Go projects, you can also use the\ntzf command-line interface (CLI) tool to quickly get the timezone name for a set\nof coordinates. To use the CLI tool, you first need to install it using the\nfollowing command:\n\n```bash\ngo install github.com/ringsaturn/tzf/cmd/tzf@latest\n```\n\nOnce installed, you can use the tzf command followed by the latitude and\nlongitude values to get the timezone name:\n\n```bash\ntzf -lng 116.3883 -lat 39.9289\n```\n\nAlternatively if you want to look up multiple coordinates efficiently you can\nspecify the ordering and pipe them to the tzf command one pair of coordinates\nper line:\n\n```bash\necho -e \"116.3883 39.9289\\n116.3883, 39.9289\" | tzf -stdin-order lng-lat\n```\n\n## Data\n\nYou can download the original data from\n\u003chttps://github.com/evansiroky/timezone-boundary-builder\u003e.\n\nThe preprocessed protobuf data can be obtained from\n\u003chttps://github.com/ringsaturn/tzf-rel\u003e, which has Go's `embedded` support.\nThese files are Protocol Buffers messages for more efficient binary\ndistribution, similar to Python wheels. You can view the\n[`pb/tzinfo.proto file`](./pb/tzinfo.proto) or its\n[HTML format documentation][pb_html] for information about the internal format.\n\nThe data pipeline for tzf can be illustrated as follows:\n\n```mermaid\ngraph TD\n    Raw[GeoJSON from evansiroky/timezone-boundary-builder]\n    Full[Full: Probuf based data]\n    Lite[Lite: smaller of Full data]\n    Compressed[Compressed: Lite compressed via Polyline]\n    Preindex[Tile based data]\n\n    Finder[Finder: Polygon Based Finder]\n    FuzzyFinder[FuzzyFinder: Tile based Finder]\n    DefaultFinder[DefaultFinder: combine FuzzyFinder and Compressed Finder]\n\n    Raw --\u003e |cmd/geojson2tzpb|Full\n    Full --\u003e |cmd/reducetzpb|Lite\n    Lite --\u003e |cmd/compresstzpb|Compressed\n    Lite --\u003e |cmd/preindextzpb|Preindex\n\n    Full --\u003e |tzf.NewFinderFromPB|Finder\n    Lite --\u003e |tzf.NewFinderFromPB|Finder\n    Compressed --\u003e |tzf.NewFinderFromCompressed|Finder --\u003e |tzf.NewDefaultFinder|DefaultFinder\n    Preindex --\u003e |tzf.NewFuzzyFinderFromPB|FuzzyFinder --\u003e |tzf.NewDefaultFinder|DefaultFinder\n```\n\nThe [complete dataset (~80MB)][full-link] can be used anywhere, but requires\nhigher memory usage.\n\nThe [lightweight dataset (~10MB)][lite-link] may not function optimally in some\nborder areas.\n\nYou can observe points with different outcomes on this [page][points_not_equal].\n\nIf a slightly longer initialization time is tolerable, the\n[compressed dataset (~5MB)][compressed-link] derived from the lightweight\ndataset will be **more suitable for binary distribution.**\n\nThe [pre-indexed dataset (~1.78MB)][preindex-link] consists of multiple tiles.\nIt is used within the `DefaultFinder`, which is built on `FuzzyFinder`, to\nreduce execution times of the raycasting algorithm.\n\n[pb_html]: https://ringsaturn.github.io/tzf/pb.html\n[full-link]: https://github.com/ringsaturn/tzf-rel/blob/main/combined-with-oceans.bin\n[lite-link]: https://github.com/ringsaturn/tzf-rel/blob/main/combined-with-oceans.reduce.bin\n[preindex-link]: https://github.com/ringsaturn/tzf-rel/blob/main/combined-with-oceans.reduce.preindex.bin\n[compressed-link]: https://github.com/ringsaturn/tzf-rel/blob/main/combined-with-oceans.reduce.compress.bin\n[points_not_equal]: https://geojson.io/#id=gist:ringsaturn/2d958e7f0a279a7411c04907f255955a\n\nI have written an article about the history of tzf, its Rust port, and its Rust\nport's Python binding; you can view it\n[here](https://blog.ringsaturn.me/en/posts/2023-01-31-history-of-tzf/).\n\n## Performance\n\nThe tzf package is intended for high-performance geospatial query services, such\nas weather forecasting APIs. Most queries can be returned within a very short\ntime, averaging around 2000 nanoseconds.\n\nHere is what has been done to improve performance:\n\n1. Using pre-indexing to handle most queries takes approximately 1000\n   nanoseconds.\n2. Using an RTree to filter candidate polygons, instead of iterating through all\n   polygons, reduces the execution times of the Ray Casting algorithm.\n3. Using a finely-tuned Ray Casting algorithm package\n   \u003chttps://github.com/tidwall/geojson\u003e to verify whether a polygon contains a\n   point.\n\nThat's all. There are no black magic tricks inside the tzf package.\n\nThe benchmark was conducted using version\n\u003chttps://github.com/ringsaturn/tzf/releases/tag/v0.16.0\u003e\n\n```\ngoos: darwin\ngoarch: arm64\npkg: github.com/ringsaturn/tzf\ncpu: Apple M3 Max\nBenchmarkDefaultFinder_GetTimezoneName_Random_WorldCities-16    \t  823786\t      1261 ns/op\t      1000 ns/p50\t      5000 ns/p90\t      8000 ns/p99\t       8 B/op\t       0 allocs/op\nBenchmarkFuzzyFinder_GetTimezoneName_Random_WorldCities-16      \t 2239102\t       572.1 ns/op\t      1000 ns/p50\t      1000 ns/p90\t      1000 ns/p99\t       8 B/op\t       0 allocs/op\nBenchmarkGetTimezoneName-16                                     \t  423015\t      2852 ns/op\t      3000 ns/p50\t      3000 ns/p90\t      4000 ns/p99\t       8 B/op\t       0 allocs/op\nBenchmarkGetTimezoneNameAtEdge-16                               \t  399050\t      3036 ns/op\t      3000 ns/p50\t      3000 ns/p90\t      4000 ns/p99\t       8 B/op\t       0 allocs/op\nBenchmarkGetTimezoneName_Random_WorldCities-16                  \t  288864\t      3867 ns/op\t      4000 ns/p50\t      6000 ns/p90\t      8000 ns/p99\t       8 B/op\t       0 allocs/op\nPASS\ncoverage: 65.5% of statements\nok  \tgithub.com/ringsaturn/tzf\t7.995s\n```\n\n- \u003chttps://ringsaturn.github.io/tzf/\u003e displays continuous benchmarking results.\n- \u003chttps://ringsaturn.github.io/tz-benchmark/\u003e displays a continuous benchmark\n  comparison with other packages.\n\n## Related Repos\n\n- \u003chttps://github.com/ringsaturn/tzf-rel\u003e Preprocessed probuf data release repo\n- \u003chttps://github.com/ringsaturn/tz-benchmark\u003e Continuous Benchmark Compared\n  with other packages\n- \u003chttps://github.com/ringsaturn/tzf-rs\u003e Rust port of tzf\n- \u003chttps://github.com/ringsaturn/tzfpy\u003e Rust port's Python binding\n- \u003chttps://github.com/ringsaturn/tzf-server\u003e HTTP\u0026Redis server build with tzf\n- \u003chttps://github.com/ringsaturn/redizone\u003e Redis compatible server build with\n  tzf-rs\n\n## Thanks\n\n- \u003chttps://github.com/paulmach/orb\u003e\n- \u003chttps://github.com/tidwall/geojson\u003e\n- \u003chttps://github.com/jannikmi/timezonefinder\u003e\n- \u003chttps://github.com/evansiroky/timezone-boundary-builder\u003e\n\n## LICENSE\n\nThis project is licensed under the [MIT license](./LICENSE) and\n[Anti CSDN License](./LICENSE_ANTI_CSDN.md)[^anti_csdn]. The data is licensed\nunder the\n[ODbL license](https://github.com/ringsaturn/tzf-rel/blob/main/LICENSE), same as\n[`evansiroky/timezone-boundary-builder`](https://github.com/evansiroky/timezone-boundary-builder)\n\n[^anti_csdn]: This license is to prevent the use of this project by CSDN, has no\n    effect on other use cases.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fringsaturn%2Ftzf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fringsaturn%2Ftzf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fringsaturn%2Ftzf/lists"}