【问题标题】:Why does mktime give me an hour less?为什么 mktime 少给我一个小时?
【发布时间】:2020-07-12 23:02:11
【问题描述】:

我想看看 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 测试。我尝试在另一个架构下使用另一个编译器,它给了我正确的值。

【问题讨论】:

  • 这可能与时区和夏令时有关吗?
  • 不应该导致从那个日期开始的秒数吗?不分时区?
  • @RobertoRocco 从那天到什么时候?
  • 秒数时间被定义为UTC,但mktime()被定义为使用本地时间;这就是区别

标签: c mktime


【解决方案1】:

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

你可以通过告诉它你是 UTC 来欺骗你的程序:

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

【讨论】:

    【解决方案2】:

    mktime 函数需要本地时间。显然,您当地时间的 00:00:00 是纪元前一小时。启动程序,将TZ 设置为UTC

    【讨论】:

      【解决方案3】:

      我想看看在 1970 年 1 月 1 日 00:00:00 它实际上是否对应于 0 秒,我写了以下内容:

      1970 年 1 月 1 日 GMT 00:00:00,UTC 对应 0 秒。

      1970 年 1 月 1 日 00:00:00 Italia 时间对应于 -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 的问题。

      【讨论】:

        【解决方案4】:

        正如其他答案所示,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-01-01
          • 2020-08-09
          • 2010-12-21
          • 1970-01-01
          • 1970-01-01
          • 2015-01-14
          • 1970-01-01
          • 2010-10-17
          • 2013-06-18
          相关资源
          最近更新 更多