为什么 mktime 少给我一个小时?

Why does mktime give me an hour less?

我想看看1970年1月1日00:00:00是否真的对应0秒,我写下了:

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

int main(void) {
    int year = 1970;
    
    struct tm t = {0};
    
    t.tm_mday = 1; // January
    t.tm_year = year - 1900;
    t.tm_hour = 0;
    t.tm_isdst = -1;
    
    printf("%ld\n", mktime(&t));
    
    return 0;
}

它给我的值为 -3600。我哪里错了?

PS:使用 GCC v.10.1 测试。我尝试在另一个架构下使用另一个编译器,它返回了正确的值。

mktime 函数使用本地时间。显然,您当地时间的 00:00:00 比纪元早一小时。启动程序 TZ 设置为 UTC

您提供给 mktime() 的时间信息是 当地 时间,因此即使夏令时/夏令时不重要,时区也很重要。

您可以通过告诉程序您使用的是 UTC 来欺骗您的程序:

$ gcc mytime.c -o mytime
$ ./mytime
28800          <-- Pacific time in the US
$ TZ=GMT0 ./mytime
0

I would like to see if at 00:00:00 on January 1, 1970 it actually corresponds to 0 seconds, and I wrote the following:

1970年1月1日00:00:00GMTUTC对应0秒

1970年1月1日00:00:00Italia时间对应-3600秒

将时区设置为 UTC,然后调用 mktime()。不幸的是,C 没有可移植的方法来执行此操作,因此建议的代码仅供说明。

setenv("TZ", "UTC", 1);
tzset();
....
mktime(&t)

time_t 不一定匹配 long。推荐转换为宽类型。

// printf("%ld\n", mktime(&t));
printf("%lld\n", (long long) mktime(&t));

t.tm_mday = 1; // January误导。 .tm_mday 是一个月中的第几天,而不是一月。

.tm_mon 是自一月以来的月份,因此初始化为 0 与一月匹配。

仅当本地时间在 1 月使用 DST 时,此处对 DST 的担忧才适用。

如其他答案所示,mktime 适用于您当地的时区。但是,许多操作系统提供了一个在 UTC 中工作的相关函数 timegm。正如预期的那样,对您的程序稍作修改,在我的计算机上打印 0:

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

int main(void)
{
    int year = 1970;
    
    struct tm t = {0};
    
    t.tm_mday = 1; // January
    t.tm_year = year - 1900;
    t.tm_hour = 0;
    t.tm_isdst = -1;
    
    printf("%ld\n", timegm(&t));
    
    return 0;
}

遗憾的是,这个功能并不规范。您可能必须定义一个特殊的“功能选择宏”才能让您的 time.h 声明它。