summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorP. J. McDermott <pj@pehjota.net>2022-03-28 19:49:46 (EDT)
committer P. J. McDermott <pj@pehjota.net>2022-03-28 20:11:53 (EDT)
commit4a3bbead361b7c58c8259c3fcfc13a04866fd622 (patch)
treebf78bf8e140b3fa617f8609cd400419a2d93e2dd /src
parent81959da8f2314e5f83ffddf79fd48b0439e345a4 (diff)
downloadatsign-4a3bbead361b7c58c8259c3fcfc13a04866fd622.zip
atsign-4a3bbead361b7c58c8259c3fcfc13a04866fd622.tar.gz
atsign-4a3bbead361b7c58c8259c3fcfc13a04866fd622.tar.bz2
datetime: Don't use mktime()/localtime() shortcuts
Diffstat (limited to 'src')
-rw-r--r--src/datetime.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/src/datetime.c b/src/datetime.c
index ccf4c29..2159bb2 100644
--- a/src/datetime.c
+++ b/src/datetime.c
@@ -86,7 +86,13 @@ _datetime_reset_tm(struct tm *tm)
static void
_datetime_normalize(struct tm *now_tm, struct tm *arg_tm, time_t *arg_sec)
{
- int wday;
+ int days_in_mon[12] = {31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31};
+
+ if (now_tm->tm_year % 4 == 0 && (now_tm->tm_year % 100 != 0 ||
+ now_tm->tm_year % 400 == 0)) {
+ days_in_mon[1] = 29;
+ }
if (arg_tm->tm_sec == INT_MIN) {
arg_tm->tm_sec = 0;
@@ -100,29 +106,37 @@ _datetime_normalize(struct tm *now_tm, struct tm *arg_tm, time_t *arg_sec)
*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_tm->tm_mday;
+ arg_tm->tm_wday = (arg_tm->tm_wday + 1) % 7;
+ if (arg_tm->tm_mday > days_in_mon[arg_tm->tm_mon]) {
+ arg_tm->tm_mday = 1;
+ ++arg_tm->tm_mon;
+ if (arg_tm->tm_mon >= 12) {
+ arg_tm->tm_mon = 0;
+ ++arg_tm->tm_year;
+ }
+ }
*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;
+ /* Only a weekday specified; try tomorrow or next week. */
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;
+ if (arg_tm->tm_wday <= now_tm->tm_wday) {
+ arg_tm->tm_mday += 7;
+ }
+ arg_tm->tm_mday += arg_tm->tm_wday - now_tm->tm_wday;
+ if (arg_tm->tm_mday > days_in_mon[arg_tm->tm_mon]) {
+ arg_tm->tm_mday -= days_in_mon[arg_tm->tm_mon];
+ ++arg_tm->tm_mon;
+ if (arg_tm->tm_mon >= 12) {
+ arg_tm->tm_mon = 0;
+ ++arg_tm->tm_year;
+ }
}
*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. */
arg_tm->tm_year = now_tm->tm_year;