From 004891c1800b77f8a1e84030b42b100484bae8a0 Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Sat, 19 Mar 2022 19:57:05 -0400 Subject: Merge branch 'feature/tests' --- (limited to 'src') diff --git a/src/datetime.c b/src/datetime.c index 7c5dcfa..230a348 100644 --- a/src/datetime.c +++ b/src/datetime.c @@ -116,19 +116,15 @@ _datetime_reset_tm(struct tm *tm) } static void -_datetime_normalize(struct tm *arg_tm, time_t *arg_sec) +_datetime_normalize(struct tm *now_tm, struct tm *arg_tm, time_t *arg_sec) { - time_t now_sec; - struct tm *now_tm; - int wday; + int wday; if (arg_tm->tm_sec == INT_MIN) { arg_tm->tm_sec = 0; } if (arg_tm->tm_mday == INT_MIN && arg_tm->tm_wday == 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; @@ -150,8 +146,6 @@ _datetime_normalize(struct tm *arg_tm, time_t *arg_sec) /* Only a weekday specified; try tomorrow or next week. Uses * same shortcut as above. */ wday = arg_tm->tm_wday; - 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; @@ -163,8 +157,6 @@ _datetime_normalize(struct tm *arg_tm, time_t *arg_sec) *arg_sec += (60 * 60 * 24) * (wday - now_tm->tm_wday); } else if (arg_tm->tm_year == INT_MIN) { /* No year specified; try this year. */ - now_sec = time(NULL); - now_tm = localtime(&now_sec); arg_tm->tm_year = now_tm->tm_year; *arg_sec = mktime(arg_tm); if (*arg_sec <= mktime(now_tm)) { @@ -179,7 +171,7 @@ _datetime_normalize(struct tm *arg_tm, time_t *arg_sec) } int -datetime_parse(const char *input, time_t *arg_sec) +datetime_parse(struct tm *now_tm, const char *input, time_t *arg_sec) { int date_fmt_len; int time_fmt_len; @@ -219,7 +211,7 @@ datetime_parse(const char *input, time_t *arg_sec) end = strptime(input, fmt_buf, &arg_tm); if (end != NULL && *end == '\0') { free(fmt_buf); - _datetime_normalize(&arg_tm, arg_sec); + _datetime_normalize(now_tm, &arg_tm, arg_sec); return 0; } } @@ -235,7 +227,7 @@ datetime_parse(const char *input, time_t *arg_sec) end = strptime(input, fmt_buf, &arg_tm); if (end != NULL && *end == '\0') { free(fmt_buf); - _datetime_normalize(&arg_tm, arg_sec); + _datetime_normalize(now_tm, &arg_tm, arg_sec); return 0; } } @@ -246,7 +238,7 @@ datetime_parse(const char *input, time_t *arg_sec) end = strptime(input, DATETIME_MISC_FMTS_[d], &arg_tm); if (end != NULL && *end == '\0') { free(fmt_buf); - _datetime_normalize(&arg_tm, arg_sec); + _datetime_normalize(now_tm, &arg_tm, arg_sec); return 0; } } diff --git a/src/datetime.h b/src/datetime.h index edff8f7..554748b 100644 --- a/src/datetime.h +++ b/src/datetime.h @@ -23,7 +23,7 @@ #include int -datetime_parse(const char *input, time_t *arg_sec); +datetime_parse(struct tm *now_tm, const char *input, time_t *arg_sec); int datetime_strftime_date(const struct tm *tm, char **out, size_t *out_sz, diff --git a/src/main.c b/src/main.c index bb4abb5..ff6c15c 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 P. J. McDermott + * Copyright (C) 2021, 2022 P. J. McDermott * * This file is part of @ * @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -56,6 +57,18 @@ static const struct option LONGOPTS_[] = { }; #endif +static struct tm EPOCH_ = { + .tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 1, + .tm_mon = 0, + .tm_year = 70, + .tm_wday = 4, + .tm_yday = 0, + .tm_isdst = -1, +}; + static void _print_usage(FILE *stream, const char *program_name) { @@ -78,18 +91,52 @@ _print_help(const char *program_name) #endif } -static void -_list_formats(void) +static struct tm * +_set_now(char buf[]) { - time_t tim; - struct tm *tm; - char *out; - size_t buf_sz; - char *buf; - size_t i; + struct tm tm; + char *endptr; + time_t t; + struct tm *tm_p; - tim = time(NULL); - tm = localtime(&tim); + if (strlen(buf) != 19) { + return NULL; + } + if (buf[4] != '-' || buf[7] != '-' || buf[10] != ' ' || + buf[13] != ':' || buf[16] != ':') { + return NULL; + } + buf[4] = '\0', buf[7] = '\0', buf[10] = '\0'; + buf[13] = '\0', buf[16] = '\0'; + tm.tm_sec = strtol(buf + 17, &endptr, 10); + if (endptr[0] != '\0') { return NULL; } + tm.tm_min = strtol(buf + 14, &endptr, 10); + if (endptr[0] != '\0') { return NULL; } + tm.tm_hour = strtol(buf + 11, &endptr, 10); + if (endptr[0] != '\0') { return NULL; } + tm.tm_mday = strtol(buf + 8, &endptr, 10); + if (endptr[0] != '\0') { return NULL; } + tm.tm_mon = strtol(buf + 5, &endptr, 10) - 1; + if (endptr[0] != '\0') { return NULL; } + tm.tm_year = strtol(buf + 0, &endptr, 10) - 1900; + if (endptr[0] != '\0') { return NULL; } + tm.tm_wday = -1; + tm.tm_yday = -1; + tm.tm_isdst = -1; + + t = mktime(&tm); + tm_p = localtime(&t); + + return tm_p; +} + +static void +_list_formats(const struct tm *tm) +{ + char *out; + size_t buf_sz; + char *buf; + size_t i; puts("Time formats:"); i = 0; @@ -168,29 +215,41 @@ _concat_args(int argc, char * const argv[]) int main(int argc, char * const argv[]) { - int opt; - char *buf; - time_t arg; - time_t now; - double dif; + bool dbg; + bool fmt; + int opt; + char *buf; + time_t now; + struct tm *now_tm; + time_t arg; + double dif; + dbg = false; + fmt = false; optind = 1; opterr = 0; #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG - while ((opt = getopt_long(argc, argv, "FhV", LONGOPTS_, NULL)) > 0) { + while ((opt = getopt_long(argc, argv, "FhVd:", LONGOPTS_, NULL)) > 0) { #else - while ((opt = getopt(argc, argv, "FhV")) > 0) { + while ((opt = getopt(argc, argv, "FhVd:")) > 0) { #endif switch (opt) { case 'F': - _list_formats(); - return EXIT_SUCCESS; + fmt = true; + break; case 'h': _print_help(argv[0]); return EXIT_SUCCESS; case 'V': _print_version(); return EXIT_SUCCESS; + case 'd': + dbg = true; + now_tm = _set_now(optarg); + if (now_tm == NULL) { + return EXIT_FAILURE; + } + break; default: _print_usage(stderr, argv[0]); #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG @@ -206,17 +265,34 @@ main(int argc, char * const argv[]) argc -= optind; argv += optind; + if (dbg == false) { + now = time(NULL); + now_tm = localtime(&now); + } + + if (fmt == true) { + _list_formats(now_tm); + return EXIT_SUCCESS; + } + buf = _concat_args(argc, argv); if (buf == NULL) { return EXIT_FAILURE; } - if (datetime_parse(buf, &arg) < 0) { + if (datetime_parse(now_tm, buf, &arg) < 0) { free(buf); return EXIT_FAILURE; } free(buf); + if (dbg == true) { + now = timegm(&EPOCH_); + dif = difftime(arg, now); + printf("%" PRId64 "\n", (int64_t) dif); + return EXIT_SUCCESS; + } + time(&now); dif = difftime(arg, now); if (dif >= 1000 * 24 * 60 * 60) { -- cgit v0.9.1