带有负秒的奇怪 mktime 逻辑

2024-01-04

我一直在使用 mktime/localtime 进行时间管理,包括一些关于日期/时间的繁重算术。

当向 mktime 提供包含负值的 struct tm 时,我注意到一些非常奇怪的事情。

采取下面的代码。 2013 年 11 月 3 日,洛杉矶的 DST 发生了变化。如果我将 tm 中的时间指定为 2013 年 11 月 4 日午夜并减去 24 小时,我将得到与 2013 年 11 月 3 日午夜相同的值。 UTC 时间有 25 小时的差异,这很好,因为 isdst=-1 可以说我们正在查看“挂钟时间”。如果减去 1440 分钟 (24*60),则相同。但是,如果我减去 86400 (24*60*60) 秒,我会得到 2013-11-03 1am。 UTC 时间有 24 小时差异。以下是以下代码的输出:

2013-11-03 00:00:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-12--27 00:00:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-11-04 -24:00:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-11-04 00:-1440:00 (gmtoff=0, isdst=-1) -> 2013-11-03 00:00:00 (gmtoff=-25200, isdst=1) -> 1383462000
2013-11-04 00:00:-86400 (gmtoff=0, isdst=-1) -> 2013-11-03 01:00:00 (gmtoff=-25200, isdst=1) -> 1383465600

对我来说这没有意义——为什么秒的处理方式与分钟、小时和天的处理方式不同?我查看了 man 和 C 标准,但没有找到任何东西。

这种行为打破了我的一些假设并使事情变得复杂。有人知道 mktime/localtime 的一个好的替代方案吗(我测试了 boost、ICU 和 tzcode,对于我的需要来说都太慢了)。

预先感谢您的任何想法:)

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* printtm(struct tm tm)
{
  static char buf[100];
  sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d (gmtoff=%ld, isdst=%d)",
    tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
    tm.tm_hour, tm.tm_min, tm.tm_sec,
    tm.tm_gmtoff, tm.tm_isdst);
  return buf;
}

void test(int y, int m, int d, int hh, int mm, int ss, int isdst)
{
  struct tm tm;
  memset(&tm, 0, sizeof(tm));
  tm.tm_year = y - 1900;
  tm.tm_mon = m - 1;
  tm.tm_mday = d;
  tm.tm_hour = hh;
  tm.tm_min = mm;
  tm.tm_sec = ss;
  tm.tm_isdst = isdst;
  printf("%s -> ", printtm(tm));
  time_t t = mktime(&tm);
  printf("%s -> %ld\n", printtm(tm), t);
}


int main()
{
  setenv("TZ", ":America/Los_Angeles", 1);
  tzset();

  test(2013,11,03, 0,0,0, -1);
  test(2013,12,-27, 0,0,0, -1);
  test(2013,11,04, -24,0,0, -1);
  test(2013,11,04, 0,-1440,0, -1);
  test(2013,11,04, 0,0,-86400, -1);

  return 0;
}

Using mktime中的值超出范围struct tm and tm_isdst==-1是有问题且不明确的。就个人而言,我认为您的系统在这里的行为方式是wrong,但标准并不清楚它应该如何表现,因此任何此类用法充其量都是不可移植的。进行算术运算struct tm,你应该确保tm_isdst预先设置为 0 或 1,以便结果明确。

请注意,执行此操作的一种简单方法是简单地调用mktime在原来的struct tm (with tm_isdst==-1),然后应用算术来确定夏令时是否有效(即填写一个确定值)tm_isdst)然后在进行算术调整后再次调用它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有负秒的奇怪 mktime 逻辑 的相关文章

随机推荐