summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/strutils.h2
-rw-r--r--include/timeutils.h13
-rw-r--r--lib/Makemodule.am5
-rw-r--r--lib/strutils.c17
-rw-r--r--lib/timeutils.c81
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 */