diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 118 |
1 files changed, 97 insertions, 21 deletions
@@ -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 <errno.h> +#include <inttypes.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> @@ -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) { |