5

I would like to see if at 00:00:00 on January 1, 1970 it actually corresponds to 0 seconds, and I wrote the following:

#include <stdio.h>
#include <time.h>

int main(void) {
    int year = 1970;
    
    struct tm t = {0};
    
    t.tm_mday = 1; // January
    t.tm_year = year - 1900;
    t.tm_hour = 0;
    t.tm_isdst = -1;
    
    printf("%ld\n", mktime(&t));
    
    return 0;
}

it gives me a value of -3600. Where am I wrong?

PS: tested with GCC v.10.1. I tried with another compiler under another architecture and it gives me back the correct value.

Roberto Rocco
  • 450
  • 2
  • 11

4 Answers4

2

The mktime function takes a time in local time. Apparently, 00:00:00 at your local time was one hour before the epoch. Launch the program with TZ set to UTC.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
2

The time info you provide to mktime() is in local time, so the timezone matters even if summer time / daylight savings time does not.

You can fool your program by telling it you're in UTC:

$ gcc mytime.c -o mytime
$ ./mytime
28800          <-- Pacific time in the US
$ TZ=GMT0 ./mytime
0
Steve Friedl
  • 3,929
  • 1
  • 23
  • 30
1

I would like to see if at 00:00:00 on January 1, 1970 it actually corresponds to 0 seconds, and I wrote the following:

00:00:00 on January 1, 1970 GMT, UTC corresponds to 0 seconds.

00:00:00 on January 1, 1970 Italia time corresponds to -3600 seconds.

Set timezone to UTC and then call mktime(). Unfortunately C does not have a portable way to do this, so the suggested code is only illustrative.

setenv("TZ", "UTC", 1);
tzset();
....
mktime(&t)

time_t does not necessarily match long. Recommend casting to a wide type.

// printf("%ld\n", mktime(&t));
printf("%lld\n", (long long) mktime(&t));

t.tm_mday = 1; // January misleads. .tm_mday is the day of the month, not January.

.tm_mon is the months since January so the initialization to 0 matches January.

Concerns about DST apply here only if the local time was using DST in January.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
1

As other answers indicate, mktime works in your local time zone. However, many operating systems offer a related function timegm that works in UTC. This slight modification of your program prints 0, as expected, on my computer:

#include <stdio.h>
#include <time.h>

int main(void)
{
    int year = 1970;
    
    struct tm t = {0};
    
    t.tm_mday = 1; // January
    t.tm_year = year - 1900;
    t.tm_hour = 0;
    t.tm_isdst = -1;
    
    printf("%ld\n", timegm(&t));
    
    return 0;
}

Regrettably, this function is not standardized. You may have to define a special "feature selection macro" to get your time.h to declare it.

zwol
  • 135,547
  • 38
  • 252
  • 361