为什么 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:00GMT,UTC对应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 声明它。
我想看看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:00GMT,UTC对应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 声明它。