2

I don't understand why difftime returns a strange value, so here is the dataset and the code I am using.

Code :

struct tm currentTime;
currentTime.tm_year = 2014 - 1900;
currentTime.tm_mon = 9 - 1;
currentTime.tm_mday = 6;
currentTime.tm_hour = 23;
currentTime.tm_min = 59;
currentTime.tm_sec = 0;
currentTime.tm_wday = 7 - 1;

struct tm previousTime;
previousTime.tm_year = 2014 - 1900;
previousTime.tm_mon = 9 - 1;
previousTime.tm_mday = 6;
previousTime.tm_hour = 23;
previousTime.tm_min = 58;
previousTime.tm_sec = 0;
previousTime.tm_wday = 7 - 1;

cout << difftime(mktime(&currentTime), mktime(&previousTime)) << endl;

This prints :

3660

Any ideas why I get this value ? I should get 60, as there is a one minute difference. I tried with some other values, and they all work.. I'm using CodeBlocks with mingw.

EDIT : Answer : use of tm_isdst solved the problem ! Bloody DST :P

struct tm currentTime;
currentTime.tm_year = 2014 - 1900;
currentTime.tm_mon = 9 - 1;
currentTime.tm_mday = 6;
currentTime.tm_hour = 23;
currentTime.tm_min = 59;
currentTime.tm_sec = 0;
currentTime.tm_wday = 7 - 1;
currentTime.tm_isdst = - 1;

struct tm previousTime;
previousTime.tm_year = 2014 - 1900;
previousTime.tm_mon = 9 - 1;
previousTime.tm_mday = 6;
previousTime.tm_hour = 23;
previousTime.tm_min = 58;
previousTime.tm_sec = 0;
previousTime.tm_wday = 7 - 1;
previousTime.tm_isdst = - 1;

cout << difftime(mktime(&currentTime), mktime(&previousTime)) << endl;
Jonathan Taws
  • 1,168
  • 11
  • 24

1 Answers1

3

Before calling mktime(), typically 7 fields of struct tm need to be set. As OP only set 6 of those, uninitialized data was in field tm_isdst causing an unexpected shift of 3600 seconds.

struct tm currentTime;
currentTime.tm_year = 2014 - 1900;
currentTime.tm_mon = 9 - 1;
currentTime.tm_mday = 6;
currentTime.tm_hour = 23;
currentTime.tm_min = 59;
currentTime.tm_sec = 0;

currentTime.tm_isdst = -1;  // **
// currentTime.tm_wday = 7 - 1; 

mktime(&currentTime);

Recommend to zero-fill struct tm as in struct tm currentTime = { 0 }; to insure all fields are specified as struct tm may contain fields in addition to the 9: int tm_sec tm_min tm_hour tm_mday tm_mon tm_year tm_wday tm_yday tm_isdst.


Notes:

The original values in tm_wday and tm_yday are ignored and re-calculated by mktime(). The other fields' original values are not restricted to their normal range and are recalculated too.

** a positive or zero value for tm_isdst causes the mktime function to presume initially that Daylight Saving Time, respectively, is or is not in effect for the specified time. A negative value causes it to attempt to determine whether Daylight Saving Time is in effect for the specified time.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Great explanation here. Basically, it's safer to zero-fill the variable before using it ? – Jonathan Taws Nov 06 '14 at 21:18
  • 1
    @Hawknight Since `struct tm` has at least the well-defined 9 fields, portable code should not risk leaving others uninitialized. In general, when using structures not-of-your-making, best to zero them before using. Had your code zero-filled, things would have been as expected, except near DST shifts. Without digging deeper, use `tm_isdst = 0 or 1` when you know the setting, else use `-1`. – chux - Reinstate Monica Nov 06 '14 at 21:26