smhk

A portable timegm alternative

Today I ran into an issue on an embedded software platform. The timegm function is nonstandard. My host unit tests pass, because timegm exists on the host, but it fails to build for the target platform because the function does not exist on that platform.

Fortunately, there is an easy solution. However, it was well hidden in my searches.

In the notes section of the timegm man page, there is a portable implementation:

#include <time.h>
#include <stdlib.h>

time_t my_timegm(struct tm *tm) {
    time_t ret;
    char *tz;

    tz = getenv("TZ");
    setenv("TZ", "", 1);
    tzset();
    ret = mktime(tm);
    if (tz) {
        setenv("TZ", tz, 1);
    } else {
        unsetenv("TZ");
    }
    tzset();
    return ret;
}

One caveat is that this portable implementation is not thread-safe, since it works by temporarily swapping out the TZ environment variable.1

As a longer term solution, there is a work-in-progress proposal (N2833) to make timegm part of C2X (the next C standard, likely to be C23).

This looks like a good proposal to me! For local time conversions, localtime and the corresponding mktime are in the standard. For UTC time conversions, gmtime is in the standard but not the corresponding timegm.


  1. Previously I wrote “[…] a solution may be to just add a mutext”. But it’s not that simple. See this blog post for more details on the problem with using setenv in multi-threaded code. ↩︎