【发布时间】:2016-12-29 03:22:46
【问题描述】:
关于 mktime 和 DST 的另一个问题
Linux、Ubuntu,时区设置为欧洲/柏林,即当前时间是 CEST:
>date
Mon Aug 22 16:08:10 CEST 2016
>date --utc
Mon Aug 22 14:08:14 UTC 2016
到目前为止一切正常。
现在我尝试运行以下代码:
#include <stdio.h>
#include <time.h>
int main()
{
struct tm tm = {0};
int secs;
tm.tm_sec = 0;
tm.tm_min = 0;
tm.tm_hour = 12;
tm.tm_mon = 9 - 1;
tm.tm_mday = 30;
tm.tm_year = 2016 - 1900;
tm.tm_isdst = 0;
secs = mktime(&tm);
printf("%i\n", secs);
tm.tm_isdst = 1;
secs = mktime(&tm);
printf("%i\n", secs);
tm.tm_isdst = -1;
secs = mktime(&tm);
printf("%i\n", secs);
return 0;
}
得到
1475233200
1475233200
1475233200
在所有三种情况下都是错误的(1 小时偏移):
>date -d @1475233200
Fri Sep 30 13:00:00 CEST 2016
所以我现在有点困惑,我的时区是否被破坏了?为什么 tm_isdst 标志被完全忽略?
编辑:@Nominal Animal 得到了答案:mktime 修改了 tm_hour!我想知道它记录在哪里?!
#include <stdio.h>
#include <time.h>
void reset(struct tm* tm){
(*tm) = (const struct tm){0};
tm->tm_sec = 0;
tm->tm_min = 0;
tm->tm_hour = 12;
tm->tm_mon = 9 - 1;
tm->tm_mday = 30;
tm->tm_year = 2016 - 1900;
}
int main()
{
struct tm tm;
int secs;
reset(&tm);
tm.tm_isdst = 0;
secs = mktime(&tm);
printf("%i\n", secs);
reset(&tm);
tm.tm_isdst = 1;
secs = mktime(&tm);
printf("%i\n", secs);
reset(&tm);
tm.tm_isdst = -1;
secs = mktime(&tm);
printf("%i\n", secs);
return 0;
}
给予
1475233200
1475229600
1475229600
【问题讨论】:
-
1) 行为似乎很奇怪。为了更好地解决问题,请在调用
mktime(&tm);后再次重置所有 字段(或至少打印它们),因为mktime()可能会调整tm字段。 2) 使用匹配的格式说明符,如printf("%i\n", (int) secs);或printf("%lld\n", (long long) secs);以避免未定义的行为。 -
这可能看起来很奇怪,但实际上并不奇怪。实际上,
mktime()修改了它的参数——特别是在这种情况下,tm.tm_hour和tm.tm_isdst字段。 -
@Nominal Animal 什么是
odd是mktime()预计不会改变tm,因为tm在前2 个案例中处于主要范围内。 ahh 可能不是第一种情况。嗯 - 夏季时间 0 的 dst 可能会更改为 1。 -
@chux 能否请您发布一个答案以便我接受,它似乎有效.. 这东西真的很奇怪
-
@Stasik:
mktime()总是 将tm_isdst更改为0或1。该行为在man 3 mktime 手册页以及更缩写形式in POSIX.1 中进行了描述(正如我在回答中解释的那样)。