struct tm 和 mktime() 关于时区转换的接口契约
Interface contract for struct tm and mktime() regarding time zone conversions
虽然 运行 下面的 C 代码,我注意到 mktime() 在调用时显然会进行一些时区转换。
void process_time(struct tm * pt) {
printf("pt %02d-%02d-%02d %02d:%02d:%02d\n", pt->tm_year, pt->tm_mon, pt->tm_mday,
pt->tm_hour, pt->tm_min, pt->tm_sec);
ret = mktime(pt);
printf("pt %02d-%02d-%02d %02d:%02d:%02d\n", pt->tm_year, pt->tm_mon, pt->tm_mday,
pt->tm_hour, pt->tm_min, pt->tm_sec);
/* more code here */
}
在某些情况下(原来是由于某些struct tm
成员没有正确初始化),我注意到在调用mktime()
之后,pt->tm_hour
少了一个比以前。本地系统时间是 UTC 以东一小时,因此对应于本地到 UTC 的转换。
根据 this source,struct tm
应该只有通常的 YYYY-MM-DD-hh-mm-ss 字段,除了工作日、一年中的某一天和一个 DST 标志——没有提及时区或 UTC 偏移量。
但是,当我检查 Ubuntu (/usr/include/time.h
) 上的结构时,我注意到两个额外的字段用于 UTC 偏移量和一个时区字符串。
struct tm
的接口契约是什么?它是否强制执行这些时区转换,如果是这样,struct tm
成员在 mktime()
规范化后应该如何解释时区?
struct tm
的接口契约是什么?
mktime()
规范的关键部分是:
The mktime function converts the broken-down time, expressed as local time ... The original values of the tm_wday
and tm_yday
components of the structure are ignored, and the original values of the other components are not restricted to the ranges indicated above. ... On successful
completion, ... components are set to represent the specified calendar
time, but with their values forced to the ranges indicated above.
C11dr §7.27.2.3 2
tm_wday
和 tm_yday
的值被忽略。成员指定年月日时分秒和.isdst
贡献,但其他平台指定的会影响结果。这可能包括纳秒、时区、UTC 偏移等成员。
健壮的代码集所有成员。
struct tm t = {0}; // clear **all** members
t.tm_year = 2018 - 1900; // Assign some members
t.tm_mon = 2 - 1;
t.tm_mday = 1; // today
t.tm_isdst = -1; // Let system determine if DST applies for this date
process_time(&t);
I noticed that after the call to mktime(), pt->tm_hour was one less than it was before.
这可能是由于 .tm_isdst < 0
。
The value of tm_isdst
is positive if Daylight Saving Time is in effect, zero if Daylight Saving Time is not in effect, and negative if the information is not available. §7.27.1 4
Footnote 320: A negative value causes it to attempt to determine whether Daylight Saving Time is in effect for the specified time.
在process_time()
中的2行加上.tm_isdst
看效果
printf("pt %02d-%02d-%02d %02d:%02d:%02d %d\n",
pt->tm_year, pt->tm_mon, pt->tm_mday,
pt->tm_hour, pt->tm_min, pt->tm_sec, pt->tm_isdst);
how are struct tm
members supposed to be interpreted regarding time zones after mktime()
has normalized them?
标准化当地时间。
chux 回答了大部分问题。这里有更多信息。
您询问了 tm_gmtoff
和 tm_zone
。这些是对 struct tm
的非标准添加,尽管它们既非常有用又非常常见。它们在 mktime
的输入时被忽略,但在输出时被设置。他们可能与您看到的异常结果无关。
虽然 运行 下面的 C 代码,我注意到 mktime() 在调用时显然会进行一些时区转换。
void process_time(struct tm * pt) {
printf("pt %02d-%02d-%02d %02d:%02d:%02d\n", pt->tm_year, pt->tm_mon, pt->tm_mday,
pt->tm_hour, pt->tm_min, pt->tm_sec);
ret = mktime(pt);
printf("pt %02d-%02d-%02d %02d:%02d:%02d\n", pt->tm_year, pt->tm_mon, pt->tm_mday,
pt->tm_hour, pt->tm_min, pt->tm_sec);
/* more code here */
}
在某些情况下(原来是由于某些struct tm
成员没有正确初始化),我注意到在调用mktime()
之后,pt->tm_hour
少了一个比以前。本地系统时间是 UTC 以东一小时,因此对应于本地到 UTC 的转换。
根据 this source,struct tm
应该只有通常的 YYYY-MM-DD-hh-mm-ss 字段,除了工作日、一年中的某一天和一个 DST 标志——没有提及时区或 UTC 偏移量。
但是,当我检查 Ubuntu (/usr/include/time.h
) 上的结构时,我注意到两个额外的字段用于 UTC 偏移量和一个时区字符串。
struct tm
的接口契约是什么?它是否强制执行这些时区转换,如果是这样,struct tm
成员在 mktime()
规范化后应该如何解释时区?
struct tm
的接口契约是什么?
mktime()
规范的关键部分是:
The mktime function converts the broken-down time, expressed as local time ... The original values of the
tm_wday
andtm_yday
components of the structure are ignored, and the original values of the other components are not restricted to the ranges indicated above. ... On successful completion, ... components are set to represent the specified calendar time, but with their values forced to the ranges indicated above.
C11dr §7.27.2.3 2
tm_wday
和 tm_yday
的值被忽略。成员指定年月日时分秒和.isdst
贡献,但其他平台指定的会影响结果。这可能包括纳秒、时区、UTC 偏移等成员。
健壮的代码集所有成员。
struct tm t = {0}; // clear **all** members
t.tm_year = 2018 - 1900; // Assign some members
t.tm_mon = 2 - 1;
t.tm_mday = 1; // today
t.tm_isdst = -1; // Let system determine if DST applies for this date
process_time(&t);
I noticed that after the call to mktime(), pt->tm_hour was one less than it was before.
这可能是由于 .tm_isdst < 0
。
The value of
tm_isdst
is positive if Daylight Saving Time is in effect, zero if Daylight Saving Time is not in effect, and negative if the information is not available. §7.27.1 4
Footnote 320: A negative value causes it to attempt to determine whether Daylight Saving Time is in effect for the specified time.
在process_time()
中的2行加上.tm_isdst
看效果
printf("pt %02d-%02d-%02d %02d:%02d:%02d %d\n",
pt->tm_year, pt->tm_mon, pt->tm_mday,
pt->tm_hour, pt->tm_min, pt->tm_sec, pt->tm_isdst);
how are
struct tm
members supposed to be interpreted regarding time zones aftermktime()
has normalized them?
标准化当地时间。
chux 回答了大部分问题。这里有更多信息。
您询问了 tm_gmtoff
和 tm_zone
。这些是对 struct tm
的非标准添加,尽管它们既非常有用又非常常见。它们在 mktime
的输入时被忽略,但在输出时被设置。他们可能与您看到的异常结果无关。