diff --git a/include/common/time.h b/include/common/time.h index 2633b1c5ee..d6bbecb8e1 100644 --- a/include/common/time.h +++ b/include/common/time.h @@ -103,6 +103,8 @@ REGPRM1 static inline struct timeval *tv_now(struct timeval *tv) */ REGPRM2 void tv_update_date(int max_wait, int interrupted); +char *timeofday_as_iso_us(int pad); + /* * sets a struct timeval to its highest value so that it can never happen * note that only tv_usec is necessary to detect it since a tv_usec > 999999 diff --git a/src/time.c b/src/time.c index e830f851ad..1a18c7641e 100644 --- a/src/time.c +++ b/src/time.c @@ -32,6 +32,9 @@ THREAD_LOCAL struct timeval after_poll; /* system date after leaving poll() static THREAD_LOCAL struct timeval tv_offset; /* per-thread time ofsset relative to global time */ static volatile unsigned long long global_now; /* common date between all threads (32:32) */ +static THREAD_LOCAL unsigned int iso_time_sec; /* last iso time value for this thread */ +static THREAD_LOCAL char iso_time_str[28]; /* ISO time representation of gettimeofday() */ + /* * adds ms to , set the result to and returns a pointer */ @@ -262,6 +265,33 @@ REGPRM2 void tv_update_date(int max_wait, int interrupted) return; } +/* returns the current date as returned by gettimeofday() in ISO+microsecond + * format. It uses a thread-local static variable that the reader can consume + * for as long as it wants until next call. Thus, do not call it from a signal + * handler. If is non-0, a trailing space will be added. It will always + * return exactly 26 or 27 characters (depending on padding) and will always be + * zero-terminated, thus it will always fit into a 28 bytes buffer. + */ +char *timeofday_as_iso_us(int pad) +{ + struct timeval new_date; + struct tm tm; + + gettimeofday(&new_date, NULL); + if (new_date.tv_sec != iso_time_sec || !new_date.tv_sec) { + get_localtime(new_date.tv_sec, &tm); + if (unlikely(strftime(iso_time_str, sizeof(iso_time_str), "%Y-%m-%dT%H:%M:%S.000000", &tm) != 26)) + strcpy(iso_time_str, "YYYY-mm-ddTHH:MM:SS.000000"); // make the failure visible but respect format. + iso_time_sec = new_date.tv_sec; + } + utoa_pad(new_date.tv_usec, iso_time_str + 20, 7); + if (pad) { + iso_time_str[26] = ' '; + iso_time_str[27] = 0; + } + return iso_time_str; +} + /* * Local variables: * c-indent-level: 8