Breder.org Software and Computer Engineering

How to Get an UTC ISO timestamp in C under Linux

TL;DR:

#include <time.h>
time_t t = time(NULL);
assert(t != ((time_t)-1)); // error handling
struct tm tm; memset(&tm, 0, sizeof(tm));
assert(gmtime_r(&t, &tm) != NULL); // error handling
printf("%04d-%02d-%02dT%02d:%02d:%02d\n",
	1900+tm.tm_year, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);

Longer answer

#include <time.h>
time_t time(time_t *tloc);

The time_t type is an integer type selected during compilation, which gets to store the number of seconds since the Unix Epoch, 1st of January 1970, UTC. Ideally sizeof(time_t) should be 8 bytes, so it doesn't overflow after 2038.

Note that the argument passed into time() should always be NULL in new code, according to man pages.

On error, time() returns a (time_t)-1 and errno is set.

#include <time.h>
struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *restrict timep, struct tm *restrict result);

The struct tm is defined as follows in Linux headers:

struct tm {
	int tm_sec;    /* Seconds (0-60) NOTE: The "60" value accomodates leap seconds */
	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 */
};

The gmtime function uses a statically-allocated struct and overwrites it in subsequent calls. Use gmtime_r so that the function outputs the result in a user-supplied struct in a thread-safe manner. (_r stands for “re-entrant”).

On error, gmtime returns a NULL pointer and errno is set.

For higher-resolution time, into the nanoseconds, one can look at calling clock_gettime() with CLOCK_REALTIME, or the simpler gettimeofday(). The man page links can be found below in “References”.

References