在 C 中解析 tzdata 数据库的工具

Tools to parse tzdata database in C

如何解析 tzdata 数据库(由 IANA 或操作系统供应商发布)以获取历史时区信息?

例如,我想知道 Asia/Tokyo 在特定时间点(如 1435100000 实际上是 2015-04-25T22:13:20+00:00 (UTC)

的格林威治标准时间偏移量是多少

您通常不需要自己解析数据文件来回答此类问题。

在大多数 Unix 版本和 Linux 下,此程序将为您提供所需的时间偏移量:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    time_t t = 1435100000;
    struct tm *tmp;
    setenv("TZ", "Asia/Tokyo", 1);
    tzset();
    tmp = localtime(&t);
    printf("offset = %ld\n", tmp->tm_gmtoff);
}

不幸的是,该程序所依赖的 tm_gmtoff 字段虽然非常有用,但却是非标准的。 (在某些版本的 Unix 下,它可能被命名为 _tm_gmtoff。在某些版本下,它可能根本不存在。)如果您没有 tm_gmtoff 可用,或者您需要您的代码具有可移植性尽可能地,你可以使用这个技巧:

time_t t2;
tmp = gmtime(&t);
t2 = mktime(tmp);
printf("offset = %ld\n", t - t2);

对于 Unix、Linux、MacOS 和任何使用 IANA 代码和数据的平台,此类程序应该在 1970 年 1 月 1 日以来的任何时区和任何时间给出正确的结果。

对于 1970 年 1 月 1 日之前的时间,普通 IANA 数据并不全面,因此如果您需要使用更早的日期和时间,您可能需要做一些不同的事情。 (IANA 数据确实涵盖了 1970 年之前的时区规则,但并不全面,也没有声称是权威的。)

据我了解,Windows下的日期时间码不保留历史时区信息,对任何历史日期总是采用当年的规则,所以在Windows下你可能需要自己编写代码,或者获取并编译 IANA 代码。 (但您仍然不需要手动解析任何数据文件。)