summaryrefslogtreecommitdiffstats
path: root/src/datetime.c
diff options
context:
space:
mode:
authorP. J. McDermott <pj@pehjota.net>2021-08-30 20:48:00 (EDT)
committer P. J. McDermott <pj@pehjota.net>2021-08-30 20:48:00 (EDT)
commit4b7a0e138d6b067cdcceaab1e703d60008653d9b (patch)
tree20a0f869397001528da036cf91ebc4164408e26e /src/datetime.c
parentc6eeed3c59e0c7a21d3bde5cd99173c287342578 (diff)
downloadatsign-4b7a0e138d6b067cdcceaab1e703d60008653d9b.zip
atsign-4b7a0e138d6b067cdcceaab1e703d60008653d9b.tar.gz
atsign-4b7a0e138d6b067cdcceaab1e703d60008653d9b.tar.bz2
datetime: Replace goto with function calls
goto is fine, but this splits up a function that had grown a little long.
Diffstat (limited to 'src/datetime.c')
-rw-r--r--src/datetime.c138
1 files changed, 72 insertions, 66 deletions
diff --git a/src/datetime.c b/src/datetime.c
index 6fecb82..d1a720d 100644
--- a/src/datetime.c
+++ b/src/datetime.c
@@ -115,6 +115,69 @@ _datetime_reset_tm(struct tm *tm)
tm->tm_isdst = INT_MIN;
}
+static void
+_datetime_normalize(struct tm *arg_tm, time_t *arg_sec)
+{
+ time_t now_sec;
+ struct tm *now_tm;
+ 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;
+ arg_tm->tm_wday = now_tm->tm_wday;
+ *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;
+ *arg_sec = mktime(arg_tm);
+ }
+ } else if (arg_tm->tm_mday == INT_MIN) {
+ /* 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;
+ arg_tm->tm_wday = now_tm->tm_wday;
+ if (wday <= now_tm->tm_wday) {
+ wday += 7;
+ }
+ *arg_sec = mktime(arg_tm);
+ *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)) {
+ /* Specified time already happened this year; use next
+ * year. */
+ ++arg_tm->tm_year;
+ *arg_sec = mktime(arg_tm);
+ }
+ } else {
+ *arg_sec = mktime(arg_tm);
+ }
+}
+
int
datetime_parse(const char *input, time_t *arg_sec)
{
@@ -125,9 +188,6 @@ datetime_parse(const char *input, time_t *arg_sec)
int t;
char *end;
struct tm arg_tm;
- time_t now_sec;
- struct tm *now_tm;
- int wday;
date_fmt_len = strlen(DATETIME_DATE_FMTS_[0]);
time_fmt_len = strlen(DATETIME_TIME_FMTS_[0]);
@@ -146,7 +206,9 @@ datetime_parse(const char *input, time_t *arg_sec)
_datetime_reset_tm(&arg_tm);
end = strptime(input, fmt_buf, &arg_tm);
if (end != NULL && *end == '\0') {
- goto found;
+ free(fmt_buf);
+ _datetime_normalize(&arg_tm, arg_sec);
+ return 0;
}
}
}
@@ -158,7 +220,9 @@ datetime_parse(const char *input, time_t *arg_sec)
_datetime_reset_tm(&arg_tm);
end = strptime(input, fmt_buf, &arg_tm);
if (end != NULL && *end == '\0') {
- goto found;
+ free(fmt_buf);
+ _datetime_normalize(&arg_tm, arg_sec);
+ return 0;
}
}
}
@@ -166,71 +230,13 @@ datetime_parse(const char *input, time_t *arg_sec)
_datetime_reset_tm(&arg_tm);
end = strptime(input, DATETIME_MISC_FMTS_[d], &arg_tm);
if (end != NULL && *end == '\0') {
- goto found;
+ free(fmt_buf);
+ _datetime_normalize(&arg_tm, arg_sec);
+ return 0;
}
}
free(fmt_buf);
fputs("Unknown date format\n", stderr);
return -1;
-
- found:
- free(fmt_buf);
-
- 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;
- arg_tm.tm_wday = now_tm->tm_wday;
- *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;
- *arg_sec = mktime(&arg_tm);
- }
- } else if (arg_tm.tm_mday == INT_MIN) {
- /* 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;
- arg_tm.tm_wday = now_tm->tm_wday;
- if (wday <= now_tm->tm_wday) {
- wday += 7;
- }
- *arg_sec = mktime(&arg_tm);
- *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)) {
- /* Specified time already happened this year; use next
- * year. */
- ++arg_tm.tm_year;
- *arg_sec = mktime(&arg_tm);
- }
- } else {
- *arg_sec = mktime(&arg_tm);
- }
-
- return 0;
}