aboutsummaryrefslogtreecommitdiff
path: root/jim-clock.c
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2019-05-20 10:23:09 +1000
committerSteve Bennett <steveb@workware.net.au>2019-05-20 15:38:54 +1000
commit4b2b03044344f9a1b637e7258db8dfd079753f10 (patch)
tree50f0701160231dbf107ca687690b9b089f9a3c95 /jim-clock.c
parentbd33d63c274c5bd13f188d961ed83e85ef0d0442 (diff)
downloadjimtcl-4b2b03044344f9a1b637e7258db8dfd079753f10.zip
jimtcl-4b2b03044344f9a1b637e7258db8dfd079753f10.tar.gz
jimtcl-4b2b03044344f9a1b637e7258db8dfd079753f10.tar.bz2
clock scan: Implement timegm() locally
Don't rely on system timegm(), and use a locally implemented timegm() that doesn't rely on changing TZ in the environment Signed-off-by: Steve Bennett <steveb@workware.net.au>
Diffstat (limited to 'jim-clock.c')
-rw-r--r--jim-clock.c33
1 files changed, 15 insertions, 18 deletions
diff --git a/jim-clock.c b/jim-clock.c
index e489af8..cc24319 100644
--- a/jim-clock.c
+++ b/jim-clock.c
@@ -98,25 +98,22 @@ static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
#ifdef HAVE_STRPTIME
-#ifndef HAVE_TIMEGM
-/* Implement a basic timegm() for system's that don't have it */
-static time_t timegm(struct tm *tm)
+/* Implement timegm() that doesn't require messing with timezone
+ * Based on: http://howardhinnant.github.io/date_algorithms.html#days_from_civil
+ */
+static time_t jim_timegm(const struct tm *tm)
{
- time_t t;
- const char *tz = getenv("TZ");
- setenv("TZ", "", 1);
- tzset();
- t = mktime(tm);
- if (tz) {
- setenv("TZ", tz, 1);
- }
- else {
- unsetenv("TZ");
- }
- tzset();
- return t;
+ int m = tm->tm_mon + 1;
+ int y = 1900 + tm->tm_year - (m <= 2);
+ int era = (y >= 0 ? y : y - 399) / 400;
+ unsigned yoe = (unsigned)(y - era * 400);
+ unsigned doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + tm->tm_mday - 1;
+ unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
+ long days = (era * 146097 + (int)doe - 719468);
+ int secs = tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
+
+ return days * 24 * 60 * 60 + secs;
}
-#endif
static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
@@ -146,7 +143,7 @@ static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
/* Now convert into a time_t */
- Jim_SetResultInt(interp, options.gmt ? timegm(&tm) : mktime(&tm));
+ Jim_SetResultInt(interp, options.gmt ? jim_timegm(&tm) : mktime(&tm));
return JIM_OK;
}