changeset 21278:fcb25852e8b7

lib: add t_strfgmtime and t_strftime
author Martti Rannanjärvi <martti.rannanjarvi@dovecot.fi>
date Thu, 08 Dec 2016 13:01:48 +0200
parents 14209dd0b677
children 136a42b63ef8
files src/lib/test-time-util.c src/lib/time-util.c src/lib/time-util.h
diffstat 3 files changed, 79 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/test-time-util.c	Thu Dec 08 19:37:30 2016 +0200
+++ b/src/lib/test-time-util.c	Thu Dec 08 13:01:48 2016 +0200
@@ -3,6 +3,8 @@
 #include "test-lib.h"
 #include "time-util.h"
 
+#include <time.h>
+
 static void test_timeval_cmp(void)
 {
 	static struct timeval input[] = {
@@ -68,8 +70,66 @@
 	test_end();
 }
 
+static void test_timestamp(const char *ts, int idx)
+{
+	/* %G:%H:%M:%S */
+	const char **t = t_strsplit(ts, ":");
+	unsigned len = str_array_length(t);
+	test_assert_idx(len == 4, idx);
+
+	/* %G - ISO 8601 year */
+	test_assert_idx(strlen(t[0]) == 4, idx);
+	unsigned v;
+	test_assert_idx(str_to_uint(t[0], &v) == 0, idx);
+	test_assert_idx(1000 <= v, idx);
+	test_assert_idx(v <= 3000, idx);
+
+	/* %H - hour from 00 to 23 */
+	test_assert_idx(strlen(t[1]) == 2, idx);
+	test_assert_idx(str_to_uint(t[1], &v) == 0, idx);
+	test_assert_idx(v <= 23, idx);
+
+	/* %M - minute from 00 to 59 */
+	test_assert_idx(strlen(t[2]) == 2, idx);
+	test_assert_idx(str_to_uint(t[2], &v) == 0, idx);
+	test_assert_idx(v <= 59, idx);
+
+	/* %S - second from 00 to 60 */
+	test_assert_idx(strlen(t[3]) == 2, idx);
+	test_assert_idx(str_to_uint(t[3], &v) == 0, idx);
+	test_assert_idx(v <= 60, idx);
+}
+
+#define TS_FMT "%G:%H:%M:%S"
+static void test_strftime_now(void)
+{
+	test_begin("t_strftime and variants now");
+
+	time_t now = time(NULL);
+	test_timestamp(t_strftime(TS_FMT, gmtime(&now)), 0);
+	test_timestamp(t_strfgmtime(TS_FMT, now), 1);
+	test_timestamp(t_strflocaltime(TS_FMT, now), 2);
+
+	test_end();
+}
+
+#define RFC2822_FMT "%a, %d %b %Y %T %z"
+static void test_strftime_fixed(void)
+{
+	test_begin("t_strftime and variants fixed timestamp");
+
+	time_t ts = 1481222536;
+	const char *exp = "Thu, 08 Dec 2016 18:42:16 +0000";
+	test_assert(strcmp(t_strftime(RFC2822_FMT, gmtime(&ts)), exp) == 0);
+	test_assert(strcmp(t_strfgmtime(RFC2822_FMT, ts), exp) == 0);
+
+	test_end();
+}
+
 void test_time_util(void)
 {
 	test_timeval_cmp();
 	test_timeval_diff();
+	test_strftime_now();
+	test_strftime_fixed();
 }
--- a/src/lib/time-util.c	Thu Dec 08 19:37:30 2016 +0200
+++ b/src/lib/time-util.c	Thu Dec 08 13:01:48 2016 +0200
@@ -55,14 +55,12 @@
 	return ((long long)secs * 1000000LL) + usecs;
 }
 
-const char *t_strflocaltime(const char *fmt, time_t t)
+static const char *strftime_real(const char *fmt, const struct tm *tm)
 {
-	const struct tm *tm;
 	size_t bufsize = strlen(fmt) + 32;
 	char *buf = t_buffer_get(bufsize);
 	size_t ret;
 
-	tm = localtime(&t);
 	while ((ret = strftime(buf, bufsize, fmt, tm)) == 0) {
 		bufsize *= 2;
 		i_assert(bufsize <= STRFTIME_MAX_BUFSIZE);
@@ -71,3 +69,18 @@
 	t_buffer_alloc(ret + 1);
 	return buf;
 }
+
+const char *t_strftime(const char *fmt, const struct tm *tm)
+{
+	return strftime_real(fmt, tm);
+}
+
+const char *t_strflocaltime(const char *fmt, time_t t)
+{
+	return strftime_real(fmt, localtime(&t));
+}
+
+const char *t_strfgmtime(const char *fmt, time_t t)
+{
+	return strftime_real(fmt, gmtime(&t));
+}
--- a/src/lib/time-util.h	Thu Dec 08 19:37:30 2016 +0200
+++ b/src/lib/time-util.h	Thu Dec 08 13:01:48 2016 +0200
@@ -36,7 +36,9 @@
 	}
 }
 
-/* Wrapper to strftime() */
+/* Wrappers to strftime() */
+const char *t_strftime(const char *fmt, const struct tm *tm) ATTR_STRFTIME(1);
 const char *t_strflocaltime(const char *fmt, time_t t) ATTR_STRFTIME(1);
+const char *t_strfgmtime(const char *fmt, time_t t) ATTR_STRFTIME(1);
 
 #endif