我想我现在明白了,人们会觉得这很混乱。把mktime()
看作是有签名的
time_t mktime_actual(struct tm *dst, const struct tm *src);
其中time_t
的结果是根据(规范化的)*src
计算出来的,而规范化的字段和夏令时是否适用于该时间,被保存到*dst
。
只是C语言的开发者在历史上只选择使用一个指针,把src
和dst
都结合起来。不过,上述逻辑仍然成立。
See the `man mktimeman页,特别是这一部分。
mktime()函数将一个分解的时间结构转换为当地时间。
表达为本地时间,转换成日历时间表示。 该
函数忽略了调用者在tm_wday和
tm_daily字段中提供的值。 在tm_isdst字段中指定的值会告知
mktime()是否在夏令时(DST)中生效。
中提供的时间是否有效:一个正值意味着DST正在生效;零意味着DST在
正值意味着DST生效;零意味着DST不生效;而负值
意味着mktime()应该(使用时区信息和系统数据库来)尝试确定DST是否生效。
负值表示mktime()应该(使用时区信息和系统数据库)试图确定在指定的时间是否有夏令时生效。
指定的时间是否生效。
mktime()函数对tm结构的字段进行修改,具体如下
如下:tm_wday和tm_daily被设置为由其他字段的内容决定的值。
其他字段的内容决定;如果结构成员超出了其
如果结构成员在其有效区间之外,它们将被归一化(因此,例如,10月40日被改为11月9日
10月被改为11月9日);tm_isdst被设置为(无论其初始值如何)正值。
tm_isdst 被设置为正值或 0,分别表示 DST 是否存在。
表示DST在指定时间是否生效。
调用mktime()还将外部变量tzname设置为关于当前时区的信息。
关于当前时区的信息。
如果指定的分解时间不能被表示为日历时间
时间(自大纪元以来的秒数),mktime()返回(time_t) -1,并且不改变分解时间结构的成员。
并不改变分解时间结构的成员。
换句话说,如果你把你的测试程序改变一下,例如变成
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
static const char *dst(const int flag)
if (flag > 0)
return "(>0: is DST)";
if (flag < 0)
return "(<0: Unknown if DST)";
return "(=0: not DST)";
static struct tm newtm(const int year, const int month, const int day,
const int hour, const int min, const int sec,
const int isdst)
struct tm t = { .tm_year = year - 1900,
.tm_mon = month - 1,
.tm_mday = day,
.tm_hour = hour,
.tm_min = min,
.tm_sec = sec,
.tm_isdst = isdst };
return t;
int main(void)
struct tm tm = {0};
time_t secs;
tm = newtm(2016,9,30, 12,0,0, -1);
secs = mktime(&tm);
printf("-1: %04d-%02d-%02d %02d:%02d:%02d %s %lld\n",
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, dst(tm.tm_isdst), (long long)secs);
tm = newtm(2016,9,30, 12,0,0, 0);
secs = mktime(&tm);
printf(" 0: %04d-%02d-%02d %02d:%02d:%02d %s %lld\n",
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, dst(tm.tm_isdst), (long long)secs);
tm = newtm(2016,9,30, 12,0,0, 1);
secs = mktime(&tm);
printf("+1: %04d-%02d-%02d %02d:%02d:%02d %s %lld\n",
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec, dst(tm.tm_isdst), (long long)secs);
return EXIT_SUCCESS;
then running it produces output
-1: 2016-09-30 12:00:00 (>0: is DST) 1475226000
0: 2016-09-30 13:00:00 (>0: is DST) 1475229600
+1: 2016-09-30 12:00:00 (>0: is DST) 1475226000
换句话说,它的行为与描述的完全一样(在上面的引文中)。这种行为在C89、C99和POSIX.1中都有记载(我想C11也有,但没有检查过)。