[!NOTE]
This package uses simplified shape data so it is not entirely accurate around the border.
By default, the binary is built as well. If you don’t want/need it, you can omit the default features and build like this:
cargo build --no-default-features
Or add in the below way:
cargo add tzf-rs --no-default-features
It’s expensive to init tzf-rs’s Finder
/FuzzyFinder
/DefaultFinder
, so
please consider reusing instances or creating one as a global variable. Below is
a global variable example:
use lazy_static::lazy_static;
use tzf_rs::DefaultFinder;
lazy_static! {
static ref FINDER: DefaultFinder = DefaultFinder::new();
}
fn main() {
// Please note coords are lng-lat.
print!("{:?}\n", FINDER.get_tz_name(116.3883, 39.9289));
print!("{:?}\n", FINDER.get_tz_names(116.3883, 39.9289));
}
For reuse,
racemap/rust-tz-service
provides
a good example.
A Redis protocol demo could be used here:
ringsaturn/redizone
.
By default, tzf-rs uses a simplified shape data. If you need 100% accurate lookup, you can use the following code to setup.
use tzf_rs::Finder;
use tzf_rs::gen::tzf::v1::Timezones;
pub fn load_full() -> Vec<u8> {
include_bytes!("./combined-with-oceans.bin").to_vec()
}
fn main() {
println!("Hello, world!");
let file_bytes: Vec<u8> = load_full();
let finder = Finder::from_pb(Timezones::try_from(file_bytes).unwrap_or_default());
let tz_name = finder.get_tz_name(139.767125, 35.681236);
println!("tz_name: {}", tz_name);
}
A full example can be found here.
The tzf-rs package is intended for high-performance geospatial query services,
such as weather forecasting APIs. Most queries can be returned within a very
short time, averaging around 3,000 nanoseconds (about 1,000ns slower than with
Go repo tzf
. I will continue improving this - you can track progress
here).
Here is what has been done to improve performance:
ringsaturn/geometry-rs
to
verify whether a polygon contains a point.That’s all. There are no black magic tricks inside the tzf-rs.
Below is a benchmark run on global cities(about 14K), and avg time is about 3,000 ns per query:
// require toolchain.channel=nightly
#![feature(test)]
#[cfg(test)]
mod benches_default {
use tzf_rs::DefaultFinder;
extern crate test;
use test::Bencher;
#[bench]
fn bench_default_finder_random_city(b: &mut Bencher) {
let finder: DefaultFinder = DefaultFinder::default();
b.iter(|| {
let city = cities_json::get_random_cities();
let _ = finder.get_tz_name(city.lng, city.lat);
});
}
}
test benches_default::bench_default_finder_random_city ... bench: 1,220.19 ns/iter (+/- 54.36)
Criterion result | Pic |
---|---|
![]() | |
Regression | ![]() |
You can view more details from latest benchmark from GitHub Actions logs.
I have written an article about the history of tzf
, its Rust port, and its
Rust port’s Python binding; you can view it
here.
ringsaturn/tzf
ringsaturn/tzf-rel
ringsaturn/geometry-rs
which is
tidwall/geometry
’s Rust port.ringsaturn/tz-benchmark
HarlemSquirrel/tzf-rb
ringsaturn/tzfpy
ringsaturn/tzf-wasm
ringsaturn/tzf-pg
The binary helps in debugging tzf-rs and using it in (scripting) languages without bindings. Either specify the coordinates as parameters to get a single time zone, or to look up multiple coordinates efficiently specify the ordering and pipe them to the binary one pair of coordinates per line.
tzf --lng 116.3883 --lat 39.9289
echo -e "116.3883 39.9289\n116.3883, 39.9289" | tzf --stdin-order lng-lat
If you are using Nixpkgs, you can install the tzf
command line tool via
unstable channel, please see more in
Nixpkgs.
This project is licensed under the MIT license. The data is
licensed under the
ODbL license, same as
evansiroky/timezone-boundary-builder
Finder
and FuzzyFinder
,
if FuzzyFinder
got no data, then use Finder
.FuzzyFinder
blazing fast for most places on earth, use a preindex data.
Not work for places around borders.