【发布时间】:2014-08-02 19:58:45
【问题描述】:
考虑以下两种方法从格式化为字符串的日期中获取纪元时间:
#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 页面。我错过了什么吗?将字符串解析为 epoch long 的好方法是什么?
编辑:
根据一些答案的建议,我应该手动将 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?
【问题讨论】:
-
官方文档:pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html。 cplusplus.com 肯定不是官方的,并且被该站点上的许多人认为是糟糕的参考。
-
对我来说它看起来像一个错误:clang 和 gcc 都没有警告未初始化的
tm tm_rand,尽管我认为他们应该这样做。我将使用最新的 gcc 和 clang 进行检查,如果问题仍然存在,请提交错误报告。 -
@Ali,很抱歉当时没有将其发布为错误报告 :) 我总是非常不愿意提交错误报告,因为我从来不确定我是对的。请让我了解似乎是什么问题,如果它是 pebkac。