summaryrefslogtreecommitdiff
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
parentbd33d63c274c5bd13f188d961ed83e85ef0d0442 (diff)
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>
-rw-r--r--auto.def2
-rw-r--r--jim-clock.c33
2 files changed, 16 insertions, 19 deletions
diff --git a/auto.def b/auto.def
index ead60aa..e7afbc6 100644
--- a/auto.def
+++ b/auto.def
@@ -118,7 +118,7 @@ cc-check-functions geteuid mkstemp realpath isatty
cc-check-functions regcomp waitpid sigaction sys_signame sys_siglist isascii
cc-check-functions syslog opendir readlink sleep usleep pipe getaddrinfo utimes
cc-check-functions shutdown socketpair isinf isnan link symlink fsync dup umask
-cc-check-functions localtime gmtime strptime timegm clock_gettime
+cc-check-functions localtime gmtime strptime clock_gettime
if {[cc-check-function-in-lib backtrace execinfo]} {
define-append LDLIBS [get-define lib_backtrace]
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;
}