Jim Tcl
Check-in [13abc622e2]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment: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>

Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 13abc622e29fd4ec35c1f651d516aa251fd05a1d
User & Date: steveb@workware.net.au 2019-05-20 05:38:53
Original User & Date: steveb@workware.net.au 2019-05-20 05:38:54
Context
2019-05-20
05:38
docs: clock: Document the -gmt flag

Signed-off-by: Steve Bennett <steveb@workware.net.au> check-in: ac0fb3f181 user: steveb@workware.net.au tags: trunk

05:38
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> check-in: 13abc622e2 user: steveb@workware.net.au tags: trunk

05:38
clock scan: Unspecified fields use the current date/time

When scanning a time with unspecified fields, those fields should use the current date/time, not 1 Jan 1900.

Signed-off-by: Steve Bennett <steveb@workware.net.au> check-in: c861d09c19 user: steveb@workware.net.au tags: trunk

Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to auto.def.

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
}

cc-check-functions ualarm lstat fork vfork system select execvpe
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

if {[cc-check-function-in-lib backtrace execinfo]} {
    define-append LDLIBS [get-define lib_backtrace]
}

if {[cc-check-functions sysinfo]} {
    cc-with {-includes sys/sysinfo.h} {







|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
}

cc-check-functions ualarm lstat fork vfork system select execvpe
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 clock_gettime

if {[cc-check-function-in-lib backtrace execinfo]} {
    define-append LDLIBS [get-define lib_backtrace]
}

if {[cc-check-functions sysinfo]} {
    cc-with {-includes sys/sysinfo.h} {

Changes to jim-clock.c.

94
95
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
111
112

113
114
115
116
117

118
119
120
121
122
123
124
125
126
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156

    Jim_SetResultString(interp, buf, -1);

    return JIM_OK;
}

#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)

{
    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;

}
#endif

static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    char *pt;
    struct tm tm;
    time_t now = time(NULL);
    /* No default format */
................................................................................
    pt = strptime(Jim_String(argv[0]), options.format, &tm);
    if (pt == 0 || *pt != 0) {
        Jim_SetResultString(interp, "Failed to parse time according to format", -1);
        return JIM_ERR;
    }

    /* Now convert into a time_t */
    Jim_SetResultInt(interp, options.gmt ? timegm(&tm) : mktime(&tm));

    return JIM_OK;
}
#endif

static int clock_cmd_seconds(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{







|
|
|
>

<
|
|
|
|
|
|
<
>
|
<
|
<
<
>

<







 







|







94
95
96
97
98
99
100
101
102
103
104
105

106
107
108
109
110
111

112
113

114


115
116

117
118
119
120
121
122
123
...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

    Jim_SetResultString(interp, buf, -1);

    return JIM_OK;
}

#ifdef HAVE_STRPTIME
/* 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)
{

    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;
}


static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
    char *pt;
    struct tm tm;
    time_t now = time(NULL);
    /* No default format */
................................................................................
    pt = strptime(Jim_String(argv[0]), options.format, &tm);
    if (pt == 0 || *pt != 0) {
        Jim_SetResultString(interp, "Failed to parse time according to format", -1);
        return JIM_ERR;
    }

    /* Now convert into a time_t */
    Jim_SetResultInt(interp, options.gmt ? jim_timegm(&tm) : mktime(&tm));

    return JIM_OK;
}
#endif

static int clock_cmd_seconds(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{