Consider these two ways to get an epoch time from a date formatted as a string:
#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;
}
Source: http://ideone.com/3xMUm8 . Essentially the difference is that tm_init is initialized with 0 and tm_rand is not. The first one triggers g++ (assuming -Wall and -W) to say:
test.cpp:4:24: warning: missing initializer for member ‘tm::tm_hour’ [-Wmissing-field-initializers]
and similar messages for other fields in the tm struct. However, if I leave out the initialization, like in the second case, valgrind tells me:
==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)
Of course, the latter is way worse than the first, but I don't like warnings either. Of course, I can initialize all the fields manually, by writing some kind of tm factory; but that would require me to write code depending on the logic of mt, and I would need two write a factory (blegh).
Is this a bug in ctime? Unfortunately I could not find (semi-)official documentation on strptime, that is, there is no cplusplus.com page on it. Am I missing something? WHat is the good way to parse a string to an epoch long?
EDIT:
As suggested by some answers, I should set the tm_isdst manually to -1, 0 or 1. However this:
#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;
}
Results in valgrind saying this:
==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)
So, should I also set _offtime?
From the official documentation of 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);
So you should be setting tm_rand.tm_isdst = -1
to tell mktime
to check DST from the locale. Alternatively you can set it to 0
or 1
.
It's unfortunate that the official documentation doesn't explicitly say that tm_isdst
is left unset, but at least it's mentioned in the example.