another one question regarding mktime and DST
Linux, Ubuntu, time zone is set to Europe/Berlin i.e. current time is CEST:
>date
Mon Aug 22 16:08:10 CEST 2016
>date --utc
Mon Aug 22 14:08:14 UTC 2016
everything okay so far.
Now I try to run the following code:
#include <stdio.h>
#include <time.h>
int main()
{
struct tm tm = {0};
int secs;
tm.tm_sec = 0;
tm.tm_min = 0;
tm.tm_hour = 12;
tm.tm_mon = 9 - 1;
tm.tm_mday = 30;
tm.tm_year = 2016 - 1900;
tm.tm_isdst = 0;
secs = mktime(&tm);
printf("%i\n", secs);
tm.tm_isdst = 1;
secs = mktime(&tm);
printf("%i\n", secs);
tm.tm_isdst = -1;
secs = mktime(&tm);
printf("%i\n", secs);
return 0;
}
and get
1475233200
1475233200
1475233200
which is in all three cases wrong (1 hour offset):
>date -d @1475233200
Fri Sep 30 13:00:00 CEST 2016
So I am a bit puzzled now, is my timezone somehow broken? Why is tm_isdst flag ignored completely?
Edit: @Nominal Animal had the answer: mktime modifies tm_hour! I wonder where it is documented?!
#include <stdio.h>
#include <time.h>
void reset(struct tm* tm){
(*tm) = (const struct tm){0};
tm->tm_sec = 0;
tm->tm_min = 0;
tm->tm_hour = 12;
tm->tm_mon = 9 - 1;
tm->tm_mday = 30;
tm->tm_year = 2016 - 1900;
}
int main()
{
struct tm tm;
int secs;
reset(&tm);
tm.tm_isdst = 0;
secs = mktime(&tm);
printf("%i\n", secs);
reset(&tm);
tm.tm_isdst = 1;
secs = mktime(&tm);
printf("%i\n", secs);
reset(&tm);
tm.tm_isdst = -1;
secs = mktime(&tm);
printf("%i\n", secs);
return 0;
}
gives
1475233200
1475229600
1475229600
When calling
mktime(&tm)
, the original values oftm
are not range restricted.Because of the the first
mktime(&tm)
call, certainlytm.tm_isdst
andtm.tm_hour
were adjusted to 1 and 11. So OP's following codetm.tm_isdst = 1;
andtm.tm_isdst = -1;
did not affect the timestamp.Better to set all fields to investigate.
I think I can now see how one would find this confusing. Think of
mktime()
as having signaturewhere the
time_t
result is calculated based on (normalized)*src
, and the normalized fields and whether daylight savings time applies at that time, is saved to*dst
.It is just that the C language developers historically chose to use only one pointer, combining both
src
anddst
. The above logic still stands, though.See the `man mktime man page, especially this part:
In other words, if you change your test program a bit, say into
then running it produces output
In other words, it behaves exactly as described (in the quote above). This behaviour is documented in C89, C99, and POSIX.1 (I think C11 also, but haven't checked).