From 4bf5cad1d4f42dc8b7321e84fba8acf4ece5d6a1 Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Sat, 28 Aug 2021 17:53:27 -0400 Subject: datetime: Further implement Simplify concatenation, factor out formats, and determine date if not specified. --- (limited to 'src/datetime.c') diff --git a/src/datetime.c b/src/datetime.c index f39f80c..74ef2d3 100644 --- a/src/datetime.c +++ b/src/datetime.c @@ -1,7 +1,27 @@ +/* + * Copyright (C) 2021 P. J. McDermott + * + * This file is part of @ + * + * @ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * @ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with @. If not, see . + */ + #define _XOPEN_SOURCE #include #include +#include #include #include #include @@ -10,42 +30,22 @@ #include "datetime.h" static const char *DATETIME_FMTS_[] = { - "%H:%M:%S", - "%I:%M:%S %p", - "%H:%M", - "%Y-%m-%dT%H:%M:%S", - "%Y-%m-%d %H:%M:%S", - "%A %B %d, %Y %H:%M:%S", +#include "datetime-formats.c" NULL }; static char * -datetime_normalize_spacing(int argc, const char *argv[]) +datetime_concat_args(int argc, const char *argv[]) { int buf_l; int i; - int l; - bool was_space; - int j; char *buf; int buf_i; + int j; buf_l = 0; for (i = 0; i < argc; ++i) { - l = strlen(argv[i]); - was_space = true; - for (j = 0; j < l; ++j) { - if (isspace(argv[i][j]) != 0) { - if (was_space == false) { - buf_l++; - was_space = true; - } - } else { - buf_l++; - was_space = false; - } - } - ++buf_l; + buf_l += strlen(argv[i]) + 1; } buf = calloc(buf_l, sizeof(*buf)); @@ -57,18 +57,8 @@ datetime_normalize_spacing(int argc, const char *argv[]) buf_i = 0; for (i = 0; i < argc; ++i) { - l = strlen(argv[i]); - was_space = true; - for (j = 0; j < l; ++j) { - if (isspace(argv[i][j]) != 0) { - if (was_space == false) { - buf[buf_i++] = ' '; - was_space = true; - } - } else { - buf[buf_i++] = argv[i][j]; - was_space = false; - } + for (j = 0; argv[i][j] != '\0'; ++j) { + buf[buf_i++] = argv[i][j]; } buf[buf_i++] = ' '; } @@ -78,27 +68,58 @@ datetime_normalize_spacing(int argc, const char *argv[]) } int -datetime_parse(int argc, const char *argv[], struct tm *tm) +datetime_parse(int argc, const char *argv[], struct tm *arg_tm) { - int e = -1; - char *buf; - int i; - char *end; + char *buf; + int i; + char *end; + time_t arg_sec; + time_t now_sec; + struct tm *now_tm; - buf = datetime_normalize_spacing(argc, argv); + buf = datetime_concat_args(argc, argv); if (buf == NULL) { return -1; } + arg_tm->tm_mday = INT_MIN; /* Sentinel */ + arg_tm->tm_sec = 0; /* Default */ + for (i = 0; DATETIME_FMTS_[i] != NULL; ++i) { - printf("%s =~ %s\n", buf, DATETIME_FMTS_[i]); - end = strptime(buf, DATETIME_FMTS_[i], tm); + /* printf("%s =~ %s\n", buf, DATETIME_FMTS_[i]); */ + end = strptime(buf, DATETIME_FMTS_[i], arg_tm); if (end != NULL && *end == '\0') { - e = 0; - break; + goto found; + } + } + + free(buf); + fprintf(stderr, "Unknown date format\n"); + return -1; + + found: + /* TODO: Support %a-only dates and optional years */ + if (arg_tm->tm_mday == INT_MIN) { + /* No date specified; try today. */ + now_sec = time(NULL); + now_tm = localtime(&now_sec); + arg_tm->tm_year = now_tm->tm_year; + arg_tm->tm_mon = now_tm->tm_mon; + arg_tm->tm_mday = now_tm->tm_mday; + arg_sec = mktime(arg_tm); + if (arg_sec <= mktime(now_tm)) { + /* Specified time already happened today; use tomorrow. + * Adding the number of seconds in a day is a shortcut + * that ignores leap seconds. One better method would + * be to increment tm_mday % days in tm_mon, etc. */ + arg_sec += 60 * 60 * 24; + now_tm = localtime(&arg_sec); + arg_tm->tm_year = now_tm->tm_year; + arg_tm->tm_mon = now_tm->tm_mon; + arg_tm->tm_mday = now_tm->tm_mday; } } free(buf); - return e; + return 0; } -- cgit v0.9.1