diff options
-rw-r--r-- | include/strutils.h | 2 | ||||
-rw-r--r-- | include/timeutils.h | 13 | ||||
-rw-r--r-- | lib/Makemodule.am | 5 | ||||
-rw-r--r-- | lib/strutils.c | 17 | ||||
-rw-r--r-- | lib/timeutils.c | 81 |
5 files changed, 117 insertions, 1 deletions
diff --git a/include/strutils.h b/include/strutils.h index 9f4339f41..f303450f5 100644 --- a/include/strutils.h +++ b/include/strutils.h @@ -212,6 +212,8 @@ static inline size_t ltrim_whitespace(unsigned char *str) extern char *strnappend(const char *s, const char *suffix, size_t b); extern char *strappend(const char *s, const char *suffix); +extern char *strfappend(const char *s, const char *format, ...) + __attribute__ ((__format__ (__printf__, 2, 0))); extern const char *split(const char **state, size_t *l, const char *separator, int quoted); extern int skip_fline(FILE *fp); diff --git a/include/timeutils.h b/include/timeutils.h index 8ed501b9d..4b6098ae1 100644 --- a/include/timeutils.h +++ b/include/timeutils.h @@ -23,6 +23,7 @@ #include <stdio.h> #include <inttypes.h> +#include <sys/time.h> typedef uint64_t usec_t; typedef uint64_t nsec_t; @@ -53,4 +54,16 @@ typedef uint64_t nsec_t; int parse_timestamp(const char *t, usec_t *usec); +/* flags for strxxx_iso() functions */ +enum { + ISO_8601_DATE = (1 << 1), + ISO_8601_TIME = (1 << 2), + ISO_8601_USEC = (1 << 3), + ISO_8601_TIMEZONE = (1 << 4), + ISO_8601_SPACE = (1 << 5) +}; +char *strtimeval_iso(struct timeval *tv, int flags); +char *strtm_iso(struct tm *tm, int flags); +char *strtime_iso(time_t t, int flags); + #endif /* UTIL_LINUX_TIME_UTIL_H */ diff --git a/lib/Makemodule.am b/lib/Makemodule.am index 054b81628..092d54e74 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -60,7 +60,8 @@ check_PROGRAMS += \ test_mangle \ test_randutils \ test_strutils \ - test_ttyutils + test_ttyutils \ + test_timeutils @@ -125,3 +126,5 @@ test_fileutils_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM test_canonicalize_SOURCES = lib/canonicalize.c test_canonicalize_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM_CANONICALIZE +test_timeutils_SOURCES = lib/timeutils.c lib/strutils.c +test_timeutils_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM_TIMEUTILS diff --git a/lib/strutils.c b/lib/strutils.c index 5a6be2dae..d5bb2db13 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -816,6 +816,23 @@ char *strappend(const char *s, const char *suffix) return strnappend(s, suffix, suffix ? strlen(suffix) : 0); } +char *strfappend(const char *s, const char *format, ...) +{ + va_list ap; + char *val, *res; + int sz; + + va_start(ap, format); + sz = vasprintf(&val, format, ap); + va_end(ap); + + if (sz < 0) + return NULL; + + res = strnappend(s, val, sz); + free(val); + return res; +} static size_t strcspn_escaped(const char *s, const char *reject) { diff --git a/lib/timeutils.c b/lib/timeutils.c index 854ef6915..c291043ed 100644 --- a/lib/timeutils.c +++ b/lib/timeutils.c @@ -338,3 +338,84 @@ int parse_timestamp(const char *t, usec_t *usec) return 0; } + +static char *format_iso_time(struct tm *tm, suseconds_t usec, int flags) +{ + char *s = NULL; + + if (flags & ISO_8601_DATE) + s = strfappend(s, "%4d-%.2d-%.2d", tm->tm_year + 1900, + tm->tm_mon + 1, tm->tm_mday); + if ((flags & ISO_8601_DATE) && (flags & ISO_8601_TIME)) + s = strnappend(s, (flags & ISO_8601_SPACE) ? " " : "T", 1); + + if (flags & ISO_8601_TIME) + s = strfappend(s, "%02d:%02d:%02d", tm->tm_hour, + tm->tm_min, tm->tm_sec); + if (flags & ISO_8601_USEC) + s = strfappend(s, ".%06ld", (long) usec); + + if (flags & ISO_8601_TIMEZONE) { + int zhour = - timezone / 60 / 60; + int zmin = labs(timezone / 60 % 60); + + s = strfappend(s, "%+02d:%02d", zhour, zmin); + } + + return s; +} + +char *strtimeval_iso(struct timeval *tv, int flags) +{ + struct tm tm = *localtime(&tv->tv_sec); + return format_iso_time(&tm, tv->tv_usec, flags); +} + +char *strtm_iso(struct tm *tm, int flags) +{ + return format_iso_time(tm, 0, flags); +} + +char *strtime_iso(time_t t, int flags) +{ + struct tm tm = *localtime(&t); + return format_iso_time(&tm, 0, flags); +} + + +#ifdef TEST_PROGRAM_TIMEUTILS + +int main(int argc, char *argv[]) +{ + struct timeval tv = { 0 }; + char *p; + + if (argc < 2) { + fprintf(stderr, "usage: %s <time> [<usec>]\n", argv[0]); + exit(EXIT_FAILURE); + } + + tv.tv_sec = strtos64_or_err(argv[1], "failed to parse <time>"); + if (argc == 3) + tv.tv_usec = strtos64_or_err(argv[2], "failed to parse <usec>"); + + p = strtimeval_iso(&tv, ISO_8601_DATE); + printf("Date: '%s'\n", p); + free(p); + + p = strtimeval_iso(&tv, ISO_8601_TIME); + printf("Time: '%s'\n", p); + free(p); + + p = strtimeval_iso(&tv, ISO_8601_DATE | ISO_8601_TIME | ISO_8601_USEC); + printf("Full: '%s'\n", p); + free(p); + + p = strtimeval_iso(&tv, ISO_8601_DATE | ISO_8601_TIME | ISO_8601_USEC | ISO_8601_TIMEZONE | ISO_8601_SPACE); + printf("Zone: '%s'\n", p); + free(p); + + return EXIT_SUCCESS; +} + +#endif /* TEST_PROGRAM */ |