c++ - 如何从 ctime 巧妙地初始化 struct tm

标签 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?

最佳答案

来自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 未设置,但至少在示例中提到了它。

关于c++ - 如何从 ctime 巧妙地初始化 struct tm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24185317/

相关文章:

c++ - 在 C++ 中,在库之间进行相似类转换的最佳方法是什么?

c++ - 在 Windows 上构建 MongoDB C++ 驱动程序

c++ - 关于模板类特化的范例

c++ - 将时间戳打包成 4 个字节

c++ - CTimeSpan 始终为零

c++ - 取消引用指向访问元素的 vector 指针

c++ - 用不同的 IDE 编译,但只有一个可以工作!

c++ - 从 C++98 升级到 C++11 导致错误

c++ - 如何在 C++11 中存储任意方法指针?

c++ - 自纪元以来的时间为-1