printf epochtime shows wrong values

252 Views Asked by At

I am experimenting with time_t variables, and this is the code in question:

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

struct tm epochtime;
time_t epochdate;

int main()
{
  epochtime.tm_mday = 19;
  epochtime.tm_mon = 10;
  epochtime.tm_year = 2002;
  epochtime.tm_hour = 0;
  epochtime.tm_min = 0;
  epochtime.tm_sec = 0 ;
  
  epochdate = mktime(&epochtime);

  printf("%ju\n",epochdate);
  printf("%ju\n", (uint32_t)epochdate);
  printf("%ju\n", (uint64_t)epochdate);
  printf("%ju\n", (uintmax_t)epochdate);
  printf("%Lf\n", epochdate);
  printf("%Le\n", epochdate);
}

I am trying to print the epochtime of a given date. The code compiles and has no errors, but when I compare what I get printed to what I calculate on this website, the values are not the same. For this given values in the example above the code output is:

210453397503
210453397503
18446744073709551615
18446744073709551615
-1.#QNAN0e+000
-1.#QNAN0e

while the link says that value should be 1034985600. I have tried multiple printf format specifiers because I found multiple answers here on how to print time_t variables, but none of them seems to work for me. Any ideas why?

2

There are 2 best solutions below

0
Marco Bonelli On BEST ANSWER

I suppose that you want to represent the date: October 19th, 2002 00:00:00, which corresponds to the epoch timestamp that you expect: 1034985600.

In such case, you are doing it wrong. Read the manual:

Broken-down time is stored in the structure tm, which is defined in <time.h> as follows:

struct tm {
    int tm_sec;    /* Seconds (0-60) */
    int tm_min;    /* Minutes (0-59) */
    int tm_hour;   /* Hours (0-23) */
    int tm_mday;   /* Day of the month (1-31) */
    int tm_mon;    /* Month (0-11) */
    int tm_year;   /* Year - 1900 */
    int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
    int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
    int tm_isdst;  /* Daylight saving time */
};

Your year should be 2002 - 1900 = 102, and your month should be 9, not 10 (months start from 0 = January).

The correct code is:

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

int main(void) {
    struct tm epochtime = {
        .tm_mday = 19,
        .tm_mon = 9,
        .tm_year = 102,
        .tm_hour = 0,
        .tm_min = 0,
        .tm_sec = 0,
        .tm_isdst = -1
    };

    time_t epochdate = mktime(&epochtime);
    if (epochdate == (time_t)(-1)) {
        perror("mktime failed");
        return 1;
    }

    printf("%" PRIuMAX "\n", (uintmax_t)epochdate);
    return 0;
}

Which correctly outputs 1034985600 as you expect.

The problem with your code is most likely that mktime is not able to correctly represent the "wrong" date you provide and returns -1, which you then print as unsigned and becomes a huge nonsensical number.

2
chux - Reinstate Monica On

printf epochtime shows wrong values

There is no specified matching print specifier for time_t. All the printf() except printf("%ju\n", (uintmax_t)epochdate); can lead to undefined behavior (UB).

... multiple answers here on how to print time-t variables, but none of them seems to work for me. Any ideas why?

time_t is a type capable of representing times.

The range and precision of times representable in clock_t and time_t are implementation-defined. C17dr § 7.27.1 4


Print using a cast. As time_t is very commonly a signed integer type, cast to a wide signed type:

time_t t;
time(&t);
printf("%jd", (intmax_t) t);
// or pre-C99
printf("%ld", (long) t);

or for wide portability at the small risk of losing some precision,

printf("%f", (double) t);

printf("%ju\n", (uintmax_t)epochdate); --> 18446744073709551615 is certainly the result of mktime(&epochtime); returning -1 due to a conversion error, likely due to range error with epochtime.tm_year = 2002;. .tm_year is the year since 1900. @pmg

Best to zero out epochtime first to initialize all members - there may be more than 9.

struct tm epochtime = {0};
epochtime.tm_mday = 19;
epochtime.tm_mon = 10 - 1;       // Months since January
epochtime.tm_year = 2002 - 1900; // Year since 1900
epochtime.tm_isdst = -1;         // Let system daylight daylight time for that date
epochdate = mktime(&epochtime);  // epochtime is assumed here to be a local time