跳至内容
Rust (tzf-rs)

Rust (tzf-rs)

安装

cargo add tzf-rs

tzf-rs 2.0 不再使用 protobuf。它读取由 ringsaturn/tzf-dist 发布的 TZF 嵌入式二进制格式(.tzb);默认的 bundled feature 把 lite 文件(~4 MB)携带在 crate 内。格式本身参见嵌入式二进制格式

两个查找器

类型数据峰值 RSS查询(随机城市 / 边界城市)
DefaultFinderlite .tzb 展开为多边形,带 FUZZY 快速路径~47 MiB221 ns / 475 ns
EmbeddedFinderlite .tzb 原地查询~10 MiB293 ns / 666 ns

数据来自 tz-benchmark 的 2026-09-14 快照,在 Apple M3 Max 上针对 2026c 数据集测得,对象为 tzf-dist 0.0.2026-c-tzb2 上的 tzf-rs 2.1.1;该测试环境中 Rust 运行时的基线为 5.8 MiB。tzf-rs 2.1 重写了 EmbeddedFinder 的查询遍历(打开时校验、按 chunk 块和端点奇偶跳过、每个 group 的纬度条带、只探测带键的预索引缩放级别),并切换到 64 点 chunk 的数据;结果不变,边界城市一项在 2.0.0 上为 4.78 µs。

DefaultFinder::new() 约需 13 ms 打开,EmbeddedFinder::new() 约需 2 ms。计数型分配器记录到 EmbeddedFinder 保留 0.2 MiB 堆内存:其数据是 &'static 的嵌入切片,另加打开时构建的 chunk 跳过块和纬度条带索引(lite 上约 100 KB)。EmbeddedFinder 适用于内存受限目标,其边界城市查询耗时约为 DefaultFinder 的 1.4 倍。其余场景参见选择查找器

复用查找器

构造过程会加载并校验整个文件,因此进程构建一个查找器并复用。用 LazyLock 静态变量持有它,不需要额外依赖:

use std::sync::LazyLock;
use tzf_rs::DefaultFinder;

static FINDER: LazyLock<DefaultFinder> = LazyLock::new(DefaultFinder::new);

fn main() {
    // 坐标采用 (经度,纬度) 顺序。
    println!("{:?}", FINDER.get_tz_name(116.3883, 39.9289));
    println!("{:?}", FINDER.get_tz_names(116.3883, 39.9289));
}

lazy_static 同样可用。LazyLock 自 Rust 1.80 起进入标准库。

查询

两个查找器提供相同的四个方法:

finder.get_tz_name(lng, lat)   // -> &str,无匹配时为空
finder.get_tz_names(lng, lat)  // -> Vec<&str>,按字典序排序
finder.timezonenames()         // -> Vec<&str>
finder.data_version()          // -> &str,例如 "2026c"
  • get_tz_name 预索引优先:FUZZY 瓦片预索引可以在不做点在多边形内判定的情况下回答大部分查询。
  • get_tz_names 在两个查找器中都走多边形精确路径,不查询预索引。它适用于点可能属于多个时区的场景;共享边界上的点属于所有与之相接的多边形。

使用自行提供的字节

use tzf_rs::{DefaultFinder, EmbeddedFinder};

let data = std::fs::read("lite.tzb")?;
let finder = DefaultFinder::from_tzb(&data)?;   // 加载期间借用,随后展开
static DATA: &[u8] = include_bytes!("../data/lite.tzb");
let finder = EmbeddedFinder::from_tzb(DATA)?;   // 不复制;查询时原地读取

EmbeddedFinder::from_tzb 接受 impl Into<Cow<'static, [u8]>>,因此来自 include_bytes!&'static [u8] 无需复制即可接管,持有所有权的 Vec<u8> 同样可以传入。两个构造函数都返回 Result<_, tzf_rs::Error>:文件在打开时会做 CRC 校验和结构校验,数据损坏时返回错误,而不产生空的查找器。

Error 带有 #[non_exhaustive],包含 MalformedProfileNoFuzzyIndex 四个变体。传入 .tzm 内存镜像字节时返回 Profile:tzf-rs 只读取 .tzb profile,M profile 由 Go 实现读取。

Cargo feature

Feature默认作用
bundled嵌入 tzf-dist 的 lite .tzb(~4 MB),启用 new()
clap构建 tzf 命令行程序
full仅 git 提供的完整精度 .tzb(~14 MB),启用 new_full()
export-geojsonGeoJSON 导出方法

fullbundled 互斥;同时启用时 crate 会触发 compile_error!。完整数据集超出 crates.io 的体积限制,因此从 git 引用:

[dependencies]
tzf-rs = { git = "https://github.com/ringsaturn/tzf-rs", rev = "v{X}.{Y}.{Z}", features = ["full"], default-features = false }
use tzf_rs::DefaultFinder;

let finder = DefaultFinder::new_full();
println!("{}", finder.get_tz_name(139.767125, 35.681236));

在库构建中去掉命令行程序:cargo build --no-default-features --features bundled

GeoJSON 导出

启用 export-geojson 后,两个查找器都提供四个导出方法:

let world = finder.to_geojson();                            // BoundaryFile
let tokyo = finder.get_tz_geojson("Asia/Tokyo");            // Option<BoundaryFile>
let tiles = finder.get_tz_preindex_geojson("Asia/Tokyo");   // Option<BoundaryFile>
let all_tiles = finder.to_preindex_geojson();               // Option<BoundaryFile>

预索引导出方法返回命名某个时区的 FUZZY 瓦片的包围矩形,即 get_tz_name 直接由预索引作答、无需回退到点在多边形内判定的区域。文件不含 FUZZY 区段时返回 None

从 v1 迁移

v1v2
DefaultFinder::new()DefaultFinder::new(),调用处不变
DefaultFinder::new_full()DefaultFinder::new_full(),调用处不变
Finder(仅多边形)DefaultFinderget_tz_names 仍为多边形精确路径
FuzzyFinder(仅瓦片)已移除;预索引是每个查找器内部的快速路径
Finder::from_compressed_topo(pb)DefaultFinder::from_tzb(bytes)
FuzzyFinder::from_pb(pb)已移除,无替代
FinderOptions / new_with_options已移除;YStripes 始终启用
finder.finder.get_tz_geojson(...)finder.get_tz_geojson(...)
FuzzyFinder 的瓦片包围盒 GeoJSONget_tz_preindex_geojson / to_preindex_geojson 取代
新增:EmbeddedFinder,原地查询且内存占用低

行为变化:

  • get_tz_names 的结果现按字典序排序。
  • DefaultFinderget_tz_name 由覆盖该点的预索引瓦片作答,与 v1 DefaultFinder 的语义一致。此前用 v1 Finder 获取多边形精确多结果的代码改调用 get_tz_names
  • 字节构造函数返回 Result,不再回退为空查找器。
  • GeoJSON 导出不再包含 protobuf 展开时保留的重复连接顶点(长度为零的线段)。查询结果不受影响。
  • 随 protobuf 一并移除的还有:Finder::from_pbFinder::from_compressed_topoFuzzyFinder::from_pbpbgen 模块、prost 依赖和 revert_timezones

v1 系列(tzf-rs 1.3.x)仍然可用,并冻结在最后一个数据版本上:v2 产物发布后,tzf-dist 不再发布 protobuf 产物,因此获取更新后的边界数据需要迁移到 v2。

集成示例

最后更新于