我一直在使用 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;
}