/tzf-rs

Get timezone via longitude&latitude in Rust in a fast way

Primary LanguageRustMIT LicenseMIT

tzf-rs: a fast timezone finder for Rust. Rust Documentation

Time zone map of the world

Note

This package uses simplified shape data so it is not entirely accurate around the border.

Build options

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

Best Practices

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() {
    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.

Performance

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:

  1. Using pre-indexing to handle most queries takes approximately 1000 nanoseconds.
  2. Using a finely-tuned Ray Casting algorithm package 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
PDF
Regression

You can view more details from latest benchmark from GitHub Actions logs.

References

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.

Bindings

LICENSE

This project is licensed under the MIT license. The data is licensed under the ODbL license, same as evansiroky/timezone-boundary-builder