Reputation: 235
I am executing below code.
int main()
{
struct tm storage={0,0,0,0,0,0,0,0,0};
char *p = NULL;
p = (char *)strptime("2012-08-25 12:23:12","%Y-%m-%d %H:%M:%S",&storage);
char buff[1024]={0};
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage);
cout << buff << endl;
storage.tm_sec += 20;
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage);
cout << buff << endl;
mktime(&storage);
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage);
cout << buff << endl;
return 0;
}
If above Program executed, It prints ' 2012-08-25 13:23:32' instead of '2012-08-25 12:23:32'. Please Help, why it is increasing tm_hour value. This works correctly if I put input date as '2012-02-25 12:23:32' in program, which is confusing.
OUtput ->
[user@rtpkvm55-vm2 root]$ ./a.out
2012-08-25 12:23:12
2012-08-25 12:23:32
2012-08-25 13:23:32
[user@rtpkvm55-vm2 root]$
Date Info on my system, -->
[user@rtpkvm55-vm2 root]$ date
Sat Aug 25 08:28:26 EDT 2012
Upvotes: 15
Views: 11464
Reputation: 1
Here is a trick to fix your code:
int main()
{
// Need to know if daylight saving is on or off, use the following trick
// Get the current time in seconds since epoch, convert it to local time,
// tm_isdst(is daylight saving) value, in the tm variable returned by the localtime(), will be set accordingly
time_t now = time(0);
struct tm *tm2= localtime(&now);
struct tm storage={0,0,0,0,0,0,0,0,tm2->tm_isdst}; // Note: used the is daylight saving on flag fetched above
char *p = NULL;
p = (char *)strptime("2012-08-25 12:23:12","%Y-%m-%d %H:%M:%S",&storage);
char buff[1024]={0};
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage);
cout << buff << endl;
storage.tm_sec += 20;
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage);
cout << buff << endl;
mktime(&storage);
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage);
cout << buff << endl;
return 0;
}
Upvotes: 0
Reputation: 797
You have to set tm_isdst
in the tm
struct otherwise it is uninitialised, and thus gets set to a random garbage value. Then, when you call mktime
depending on which random garbage is in tm_isdst
variable, it either applies daylight saving time or it doesn't, seemingly unpredictably.
However, if you set it to -1
, you tell mktime
that you don't know whether daylight saving time is in effect, so the first call to mktime
will fix it.
Therefore, the simplest way to fix this issue is adding:
storage.tm_isdst = -1;
before calling mktime
.
Upvotes: 1
Reputation: 6055
What happens
The date you specified has daylight savings in effect but when calling mktime
, storage.tm_isdst
is zero. mktime
sees this and thinks "hey, they gave me a date with an incorrect daylight savings flag, lets fix it". Then it sets tm_isdst
to 1 and changes tm_hour
.
See also this answer.
To fix it
timegm
instead of mktime
mktime
(see also example from timegm
) :
setenv("TZ", "", 1); tzset(); mktime();
boost::locale::date_time
page before picking one)Upvotes: 22
Reputation: 42588
Wow, there just is no way around it. It must be a bug in your system's implementation of mktime(3). mktime(3) should not alter the struct tm *
passed to it.
I would suggest checking the value of storage.tm_isdst
. Try setting it to 0 to ensure it's not confused about DST. If that doesn't work, try setting it to -1 to let it auto determine the proper value.
mktime - convert broken-down time into time since the Epoch
A positive or 0 value for tm_isdst causes mktime() to presume initially that Daylight Savings Time, respectively, is or is not in effect for the specified time. A negative value for tm_isdst causes mktime() to attempt to determine whether Daylight Saving Time is in effect for the specified time.
I was wrong about mktime(3) not modifying struct tm *
. It is the correct behavior to normalize the value.
Upvotes: 5