From e130ed9b3a982b36b75d4fbb225ad1fe8e16a7de Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Tue, 31 Aug 2021 20:54:28 -0400 Subject: Add option to list supported formats --- (limited to 'src/datetime.c') diff --git a/src/datetime.c b/src/datetime.c index 0056017..1a3bbba 100644 --- a/src/datetime.c +++ b/src/datetime.c @@ -19,8 +19,10 @@ #define _XOPEN_SOURCE +#include #include #include +#include #include #include #include @@ -87,16 +89,16 @@ static const char *DATETIME_TIME_FMTS_[] = { }; static const char *DATETIME_MISC_FMTS_[] = { /* ISO 8601: 1969-12-31 delimited by "T" */ - " %Y-%m-%dT%H:%M:%S ", - " %Y-%m-%dT%H:%M ", + " %Y-%m-%dT%H:%M:%S ", + " %Y-%m-%dT%H:%M ", /* ISO 8601: 19691231 delimited by "T" */ - " %Y%m%dT%H%M%S ", - " %Y%m%dT%H%M ", + " %Y%m%dT%H%M%S ", + " %Y%m%dT%H%M ", /* 19691231 */ - " %Y%m%d %I%M%S %p ", - " %Y%m%d %H%M%S ", - " %Y%m%d %I%M %p ", - " %Y%m%d %H%M ", + " %Y%m%d %I%M%S %p ", + " %Y%m%d %H%M%S ", + " %Y%m%d %I%M %p ", + " %Y%m%d %H%M ", /* Wed Dec 31 19:00:01 1969 */ " %a %b %d %H:%M:%S %Y ", }; @@ -244,3 +246,109 @@ datetime_parse(const char *input, time_t *arg_sec) fputs("Unknown date format\n", stderr); return -1; } + +static void +_datetime_copy_trim_fmt(char *buf, const char *fmt) +{ + int buf_i; + int l; + bool was_space; + int i; + + buf_i = 0; + l = strlen(fmt); + was_space = true; + for (i = 0; i < l; ++i) { + if (isspace(fmt[i]) != 0) { + if (was_space == false) { + buf[buf_i++] = ' '; + was_space = true; + } + } else { + buf[buf_i++] = fmt[i]; + was_space = false; + } + } + if (buf_i > 0) { + buf[buf_i - 1] = '\0'; + } else { + buf[0] = '\0'; + } +} + +static int +_datetime_strftime(const char *fmts[], const struct tm *tm, char **out, + size_t *out_sz, char **buf, size_t *i) +{ + if (*buf == NULL) { + *buf = calloc(strlen(fmts[0]), sizeof(**buf)); + if (*buf == NULL) { + fprintf(stderr, "Failed to allocate buffer: %s\n", + strerror(errno)); + return -1; + } + } + if (*out == NULL) { + *out_sz = strlen(fmts[0]); + *out = calloc(*out_sz, sizeof(**out)); + if (*out == NULL) { + fprintf(stderr, "Failed to allocate buffer: %s\n", + strerror(errno)); + return -1; + } + } + + *buf[0] = '\0'; + while (*buf[0] == '\0') { + _datetime_copy_trim_fmt(*buf, fmts[*i]); + ++*i; + } + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + while (strftime(*out, *out_sz, *buf, tm) == 0) { +#pragma GCC diagnostic pop + ++*out_sz; + *out = realloc(*out, *out_sz * sizeof(**out)); + if (*out == NULL) { + fprintf(stderr, "Failed to allocate buffer: %s\n", + strerror(errno)); + return -1; + } + } + + return 1; +} + +int +datetime_strftime_date(const struct tm *tm, char **out, size_t *out_sz, + char **buf, size_t *i) +{ + if (*i >= sizeof(DATETIME_DATE_FMTS_) / sizeof(DATETIME_DATE_FMTS_[0])){ + return 0; + } + + return _datetime_strftime(DATETIME_DATE_FMTS_, tm, out, out_sz, buf, i); +} + +int +datetime_strftime_time(const struct tm *tm, char **out, size_t *out_sz, + char **buf, size_t *i) +{ + if (*i >= sizeof(DATETIME_TIME_FMTS_) / sizeof(DATETIME_TIME_FMTS_[0])){ + return 0; + } + + return _datetime_strftime(DATETIME_TIME_FMTS_, tm, out, out_sz, buf, i); +} + +int +datetime_strftime_misc(const struct tm *tm, char **out, size_t *out_sz, + char **buf, size_t *i) +{ + if (*i >= sizeof(DATETIME_MISC_FMTS_) / sizeof(DATETIME_MISC_FMTS_[0])){ + return 0; + } + + return _datetime_strftime(DATETIME_MISC_FMTS_, tm, out, out_sz, buf, i); +} -- cgit v0.9.1