跳至内容

术语表

API 行为

坐标顺序

所有 tzf 实现均采用 (经度,纬度) 顺序,与 GeoJSON 和大多数地理 API 一致。请注意,部分系统(Google Maps URL、许多教材)使用 (纬度,经度),传递数值前请仔细确认。

多时区

位于时区边界附近的点可能属于多个时区。使用多结果 API 获取所有候选项:

语言函数
GoGetTimezoneNames()
Rustget_tz_names()
Pythonget_tzs()
SwiftgetTimezones()

查找器

v2 通过返回接口的构造函数提供查找器。v1 的 Finder / FuzzyFinder / DefaultFinder 类见 v1 术语

默认查找器

Go 为 NewDefaultFinder(),Rust 为 DefaultFinder::new()。读取 lite 数据集,以 FUZZY 预索引作为快速路径,其后是多边形几何数据。在 Go 中,多边形存储原地引用 .tzm 内存镜像:~12 MB 堆加上 ~10 MB 只读数据,在 Apple M3 Max 上针对 2026c 数据集每次查询 298 ns。在 Rust 中,同一构造函数把 lite.tzb 展开为多边形,峰值 RSS 约 47 MiB,查询 221 ns(2026-09-14 快照)。

嵌入式查找器

Go 为 NewEmbeddedFinder(),Rust 为 EmbeddedFinder::new()。原地查询 lite .tzb,除文件字节外只保留打开时构建的小型索引(2.1 起,Go 约 30 KB,Rust 约 100 KB)。预索引未覆盖该点时,边界城市的查询约为 1 µs(2026-09-14 快照中 Go p50 为 1,000 ns,Rust 平均值为 666 ns)。适用于嵌入式目标、内存受限的进程和无文件系统的部署。

完整精度查找器

Go 为 NewFullFinder(),Rust 为 DefaultFinder::new_full()。读取展开到内存中的完整精度数据集:Go 中常驻约 145 MB。结果与未简化的边界数据一致。

数据版本

时区边界数据的版本标识,例如 "2026c"。跟踪IANA 时区数据库的发布,通过evansiroky/timezone-boundary-builder。可通过 data_version() (Python)、DataVersion() (Go) 或 data_version() (Rust) 在运行时访问。tzf-dist 的三个产物携带相同的值。

数据格式

.tzb

E profile 的 TZF 嵌入式二进制文件:紧凑的传输格式,几何数据以分块的 zigzag-LEB128 varint 流存储。所有实现都读取该格式。参见嵌入式二进制格式

.tzm

M profile 的 TZF 嵌入式二进制文件:同一份数据,几何数据以一个扁平的 (int32, int32) 对数组存储,文件布局与查询时的结构一致。由 Go 实现读取;tzf-rs 对此类文件返回 Error::Profile。由使用它的主机通过 tzf 的 cmd/tzb2tzm 生成。

Profile E / Profile M

偏移 48 处的文件头字节决定 TZF 嵌入式二进制文件的布局:0 为 E(embedded,.tzb),1 为 M(memory image,.tzm)。必需区段按 profile 区分,跨 profile 的区段类型会被拒绝。

FUZZY 区段

区段类型 10,瓦片预索引,存储为一个有序的打包瓦片 ID 数组及其时区索引。tzf-dist 的三个产物都包含该区段。它是单名称查询的快速路径;多结果 API 不查询它。在 2026c 数据集上包含 87,572 个瓦片,其中 156 个命名两个时区,约 880 KB。

原地加载与展开加载

原地: 查找器按每次查询的需要,从文件字节中读取几何数据。打开时不解码几何数据,堆上只有打开时构建的小型索引,预索引未命中时查询约 1 µs。对应 Go 的 NewEmbeddedFinderx.NewFinderFromTZBReaderAt 和 Rust 的 EmbeddedFinder

原地引用: M profile 按查询时的布局存储点,因此环存储直接指向映射的字节,不解码也不复制。源字节必须保持存活且不被修改。对应 Go 的 NewFinderFromTZM

展开: 打开时把文件解码为多边形对象。打开开销和常驻内存较高,查询为纳秒级。对应 Go 的 NewFinderFromTZBNewFullFinder 和 Rust 的 DefaultFinder

数据文件

tzf-dist

当前数据分发仓库(ringsaturn/tzf-dist), 于 2026 年春季推出。以 Go 模块和 Rust crate 形式分发处理后的二进制数据。替代 tzf-rel / tzf-rel-lite 仓库。

数据文件

tzf-dist 提供的三个文件,均采用TZF 嵌入式二进制格式 1.1, 都带有 FUZZY 区段并携带相同的 data_version

文件Profile大小用途
lite.tzbE约 4 MB拓扑简化数据;crates.io 与 PyPI 分发的内容
lite.tzmM约 10 MB同一份数据的内存镜像,由 Go NewDefaultFinder 读取
full.tzbE约 14 MB完整精度数据;在 Rust crate 中仅由 git 提供

full.tzm 不做发布:把完整数据集按 M 布局展开约为 67 MB。

tzf-rel / tzf-rel-lite(已停止)

先前的数据分发仓库,已被 tzf-dist 取代。其中的 protobuf 产物不再发布。

v1 术语

以下术语适用于 v1 系列(tzf v1.2.x、tzf-rs 1.3.x、tzfpy 1.3.x),该系列冻结在最后一个 protobuf 数据版本上:

术语在 v1 中的含义v2 中的对应物
FuzzyFinder仅使用瓦片预索引的查找器,覆盖瓦片之外返回空结果已移除;预索引是每个查找器内部的快速路径
Finder仅使用多边形的查找器默认查找器;多结果 API 仍走多边形精确路径
DefaultFinder预索引加多边形回退默认查找器,作用相同
CompressedTopoTimezones承载去重并经 polyline 编码几何数据的 protobuf 消息.tzb / .tzm
PreindexTimezones承载瓦片预索引的 protobuf 消息FUZZY 区段

算法与索引

多边形简化

使用 Ramer-Douglas-Peucker (RDP) 算法减少时区边界多边形中的点数。v2 的 lite 数据集使用 0.001 度的 epsilon, 边界位移上限为 111.2 m,认证结果见BORDER_CHANGE.md

拓扑感知简化

对逐多边形 RDP 的增强,修复共享边界处的间隙/重叠问题 (tzf#183)。

首先检测相邻多边形之间的共享边,仅简化一次,然后替换回两个多边形,防止简化过程产生新的间隙或重叠。在 tzf v1.1.0(2026 年春季)中引入。实现细节:internal/topology/README.md

瓦片索引

预计算的空间索引,在 v2 中存储为 FUZZY 区段。参照地图瓦片格式, 将地球表面在固定缩放级别上划分为四边形瓦片。仅当某个时区多边形完全包含该瓦片时,它才进入索引,边界瓦片被排除在外。内部点因此可以通过瓦片查找解析,无需做多边形判定。

YStripes 索引

从 Josh Baker 的 tidwall/tg 移植的逐多边形空间索引。将每个多边形的边划分为水平条带。对于给定的查询点,仅测试匹配条带中的边。自 tzf v1.1.0 (Go) 和 tzf-rs v1.2.0 (Rust) 起默认启用;v2 中始终启用,.tzm 加载器在打开时并行重建该索引。嵌入式二进制格式的区段类型 14 为该索引保留了一种序列化形式,当前不输出。算法详情:POLYGON_INDEXING.md

内部实现

CGO vs PyO3

tzfpy 最初通过 CGO 调用 Go 实现,编译为 .so 文件。自 v0.11.0 起改为使用 PyO3 封装 tzf-rs (Rust)。 PyO3 无需在 FFI 边界手动管理对象生命周期, 消除了 CGO 导致的内存泄漏问题(tzf#63), 并为 CPU 密集型工作负载提供更好的吞吐量。

最后更新于