mktime()奇怪地改变了日期

时间:2014-07-25 18:36:40

标签: c linux

我现在正在使用gcc编译器在我的RedHat Linux机器上编写一个C程序,它将接受两个日期作为输入并计算它们之间的差异。

但是,我发现了mktime()的奇怪行为,如下面的代码段所示。


struct tm t;
t.tm_year=4;
t.tm_mon=9;
t.tm_mday=30;
t.tm_hour=0;
t.tm_min=0;
t.tm_sec=0;

printf("%d-%d-%d %d:%d:%d\n", t.tm_year, t.tm_mon, t.tm_day, t.tm_hour, t.tm_min, t.tm_sec);
//result: 4-9-30 0:0:0, which means 1904 Oct 30 00:00:00

mktime(&t);

printf("%d-%d-%d %d:%d:%d\n", t.tm_year, t.tm_mon, t.tm_day, t.tm_hour, t.tm_min, t.tm_sec);
//result: 4-9-29 23:36:36, which means 1904 Oct 29 23:36:36

正如您所看到的,struct tmmktime()之后被转移,这看似不合理。

我做了很多测试,我发现这种奇怪的行为只发生在1904年10月30日00:00:00 - 00:23:24之间的日期分配。

此外,我在我的unix服务器(HP-UX)中测试了相同的代码,它运行完美,没有任何转移。

我想知道以前是否有人有过类似的经历,如果有人能给我一些关于发生了什么的提示?

我在香港时区跑步。

1 个答案:

答案 0 :(得分:6)

mktime()函数假定输入表示本地时间。在不同时间,不同地点的当地时间发生了许多奇怪的变化。

了解您的时区是有帮助的。如果您将时区设置为UTC,我怀疑问题会消失。

我自己没有看到这个问题(我在太平洋夏令时,UTC以西7小时)。

这与卢森堡同年6月的时间变化类似,记录here,当地时钟向前移动了35分24秒。 1904年10月30日是一个星期天,这可能是这种转变的时候。

另见this question关于1927年上海的时间变化(恰好有Jon Skeet得分最高的答案)。

更新:感谢Frxstrem的评论,找到了它。 1904年10月30日,从LMT到HKT,香港的时间发生了变化。如果(a)您的时区设置为香港时间,并且(b)您的系统的时区库足够详细以反映此特定更改,我预计会出现症状。

http://www.timeanddate.com/time/change/hong-kong/hong-kong?year=1904


以下是您的程序的修改版本,可以更清楚地显示问题:

#include <time.h>
#include <stdio.h>
int main(void) {
    struct tm t = {
        .tm_year  = 4,
        .tm_mon   = 9,
        .tm_mday  = 30,
        .tm_hour  = 0,
        .tm_min   = 0,
        .tm_sec   = 0,
        .tm_isdst = -1, /* let mktime() figure it out */
    };

    printf("%04d-%02d-%02d %02d:%02d:%02d\n",
           1900+t.tm_year, 1+t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
    // output: 1904-10-30 00:00:00

    mktime(&t);

    printf("%04d-%02d-%02d %02d:%02d:%02d\n",
           1900+t.tm_year, 1+t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
    // output: 1904-10-29 23:36:42
}

它为tm_isdst成员分配一个值,而你的成员不会这样做;如果未初始化值,则可能会出现不可预测的行为。此外,您的计划拼错了tm_mday tm_day

这是我系统上的输出:

$ ./c
1904-10-30 00:00:00
1904-10-30 00:00:00
$ TZ=Asia/Hong_Kong ./c
1904-10-30 00:00:00
1904-10-29 23:36:42
$ 

关于我如何能够相当快地解决这个问题的一些背景知识(这可能对其他人看到类似症状有帮助):

这个问题强烈提醒我this one,我之所以熟悉,只是因为Stack Overflow上的highest-scoring answerhighest-scoring user。那是纯粹的运气。

由于我最初不知道时区,谷歌搜索“1904年时间变化”出现this page讨论卢森堡同年的类似时间变化。世界其他地方在同一时间也做了类似的变化,这可能是向现代标准时区过渡的一部分。

Frxstrem的评论指出:谷歌搜索“1904年香港时间变化”发现this page