如何从ctime整齐地初始化struct tm

时间:2014-06-12 13:11:42

标签: c++ c++11 ctime

考虑以下两种方式从格式化为字符串的日期获取纪元时间:

#include <iostream>

int main() {
    struct tm tm_init = {0};
    strptime("2012-10-26 16:00", "%Y-%m-%dT %H:%M", &tm_init);
    long epoch = mktime(&tm_init);

    struct tm tm_rand;
    strptime("2012-10-26 16:00", "%Y-%m-%dT %H:%M", &tm_rand);
    epoch = mktime(&tm_rand);

    return 0;
}

来源:http://ideone.com/3xMUm8。本质上,区别在于tm_init初始化为0而tm_rand不是。第一个触发g ++(假设-Wall和-W)说:

test.cpp:4:24: warning: missing initializer for member ‘tm::tm_hour’ [-Wmissing-field-initializers]

和tm结构中其他字段的类似消息。但是,如果我省略初始化,就像第二种情况一样,valgrind告诉我:

==9892== Conditional jump or move depends on uninitialised value(s)
==9892==    at 0x51E957C: __offtime (offtime.c:40)
==9892==    by 0x51EBBE7: __tz_convert (tzset.c:653)
==9892==    by 0x51E9EDB: __mktime_internal (mktime.c:310)
==9892==    by 0x400786: main (test.cpp:10)

当然,后者比第一次更糟糕,但我也不喜欢警告。当然,我可以通过编写某种tm工厂手动初始化所​​有字段;但这需要我根据mt的逻辑编写代码,我需要两个写一个工厂(blegh)。

这是ctime中的错误吗?不幸的是我无法找到关于strptime的(半)官方文档,也就是说,它上面没有cplusplus.com页面。我错过了什么吗?什么是良好的方法将字符串解析为一个历元长?

修改

根据一些答案的建议,我应该手动将tm_isdst设置为-1,0或1.但是这样:

#include <iostream>

int main() {
    struct tm tm;
    strptime("2012-10-26 16:00", "%Y-%m-%dT %H:%M", &tm);
    tm.tm_isdst = 0;
    long epoch = mktime(&tm);
    return 0;
}

valgrind的结果说:

==11329== Conditional jump or move depends on uninitialised value(s)
==11329==    at 0x51E9917: __offtime (offtime.c:83)
==11329==    by 0x51EBBE7: __tz_convert (tzset.c:653)
==11329==    by 0x51EA513: __mktime_internal (mktime.c:310)
==11329==    by 0x40078D: main (test.cpp:7)

那么,我还应该设置_offtime吗?

2 个答案:

答案 0 :(得分:8)

来自strptime的官方文档:

struct tm tm;
time_t t;
strptime("6 Dec 2001 12:33:45", "%d %b %Y %H:%M:%S", &tm);
tm.tm_isdst = -1;      /* Not set by strptime(); tells mktime()
                          to determine whether daylight saving time
                          is in effect */
t = mktime(&tm);

因此,您应该设置tm_rand.tm_isdst = -1告诉mktime从区域设置中检查DST。或者,您可以将其设置为01

令人遗憾的是,官方文档没有明确说明tm_isdst未设置,但至少在示例中提到过。

答案 1 :(得分:1)

我不认为strptimetm_isdst做任何事情,并且不会处理时区(根据变化,完全或根本不会)。另一方面,mktime需要为其计算设置tm_isdst,因此可能未初始化的依赖关系会传播到其他代码中。简而言之,您需要决定如何处理时区处理......