ddomnik
ddomnik

Reputation: 73

How to get local time in seconds (unix epoch)?

I am trying to get the local time in seconds (unix epoch) when a timezone is set. For e.g.

1643371200 is 2022-01-28 12:00:00 with UTC0

this can be read via gettimeofday(tv, NULL) as seconds with the timeval struct.
Now let's say I set my local timezone to Europe/Berlin via setenv("TZ","CET-1CEST,M3.5.0,M10.5.0/3",1).

When I use

localtime_r(&now, &local_tv);
char strftime_buf[64];
strftime(strftime_buf, sizeof(strftime_buf), "%c", &local_tv);
printf("get local time: %s", strftime_buf);

this prints 2022-01-28 13:00:00 as expected (+1h).
Now I used mktime(&local_tv) as I thought this will give me my local time in seconds. But it's still 1643371200 (12:00:00). And when I use mktime() with gettimeofday() I get 1 hour less, so 11:00:00 ...

Upvotes: 1

Views: 1049

Answers (1)

ikegami
ikegami

Reputation: 386706

So why is mktime() giving me 1643371200 when used with localtime_r()

2022-01-28T13:00:00+01:00 is 1643371200 seconds later than 1970-01-01T00:00:00+00:00, the epoch used on Linux.

mktime is literally the inverse operation of localtime, so of course mktime(localtime(time)) gives time.

                time /
             gettimeofday
                  |
+-----------------+-----------------+
|                 |                 |
|                 v                 |
|             Epoch time            |
|                 |                 |
|          +------+------+          |
|          |             |          |
|          v             v          |
|      localtime       gmtime       |
|          |             |          |
|          v             v          |
|     Broken down     Broken down   |
|     local time      UTC+0 time    |
|          |             |          |
|          v             v          |
|       mktime /     _mkgmtime* /   |
|      timelocal*     timegm*       |
|          |             |          |
+----------+             +----------+

how do I get 1643374800 ?

You appear to want the number of seconds since 1970-01-01T00:00:00 local time.

If you want this, you are doing something wrong. There is no need for this value.[1]

To find the number of seconds between two times, start by converting them to epoch times if they aren't already. Then simply subtract one from the other.

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

int main( void ) {
   setenv( "TZ", "Europe/Berlin", 1 );
   tzset();

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

   time_t base_epoch = mktime( &base_tm );

   time_t now_epoch = 1643371200l;  // time( NULL );

   printf( "%" PRIi64 "\n", (int64_t)( now_epoch - base_epoch ) );  // 1643374800
}

  1. It might be useful in correcting something that was done incorrectly.

Upvotes: 1

Related Questions