4 * Implements the clock command
7 #include "jimautoconf.h"
9 /* For strptime() - currently nothing sets this */
10 #ifdef STRPTIME_NEEDS_XOPEN_SOURCE
12 #define _XOPEN_SOURCE 500
26 #include <jim-subcmd.h>
28 #ifdef HAVE_SYS_TIME_H
32 struct clock_options
{
37 /* Parses the options ?-format string? ?-gmt boolean? and fills in *opts.
38 * Any options not present are not set.
41 * Returns JIM_OK or JIM_ERR and sets an error result.
43 static int parse_clock_options(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
, struct clock_options
*opts
)
45 static const char * const options
[] = { "-gmt", "-format", NULL
};
46 enum { OPT_GMT
, OPT_FORMAT
, };
49 for (i
= 0; i
< argc
; i
+= 2) {
51 if (Jim_GetEnum(interp
, argv
[i
], options
, &option
, NULL
, JIM_ERRMSG
| JIM_ENUM_ABBREV
) != JIM_OK
) {
56 if (Jim_GetBoolean(interp
, argv
[i
+ 1], &opts
->gmt
) != JIM_OK
) {
61 opts
->format
= Jim_String(argv
[i
+ 1]);
68 static int clock_cmd_format(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
70 /* How big is big enough? */
74 struct clock_options options
= { 0, "%a %b %d %H:%M:%S %Z %Y" };
77 if (Jim_GetWide(interp
, argv
[0], &seconds
) != JIM_OK
) {
83 if (parse_clock_options(interp
, argc
- 1, argv
+ 1, &options
) == JIM_ERR
) {
88 tm
= options
.gmt
? gmtime(&t
) : localtime(&t
);
90 if (tm
== NULL
|| strftime(buf
, sizeof(buf
), options
.format
, tm
) == 0) {
91 Jim_SetResultString(interp
, "format string too long or invalid time", -1);
95 Jim_SetResultString(interp
, buf
, -1);
102 /* Implement a basic timegm() for system's that don't have it */
103 static time_t timegm(struct tm
*tm
)
106 const char *tz
= getenv("TZ");
121 static int clock_cmd_scan(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
125 /*time_t now = time(NULL);*/
126 /* No default format */
127 struct clock_options options
= { 0, NULL
};
133 if (parse_clock_options(interp
, argc
- 1, argv
+ 1, &options
) == JIM_ERR
) {
136 if (options
.format
== NULL
) {
140 /* Set unspecified fields to 0, e.g. HH:MM becomes 00:00 */
141 memset(&tm
, 0, sizeof(tm
));
142 /* But this is 1-based */
145 pt
= strptime(Jim_String(argv
[0]), options
.format
, &tm
);
146 if (pt
== 0 || *pt
!= 0) {
147 Jim_SetResultString(interp
, "Failed to parse time according to format", -1);
151 /* Now convert into a time_t */
152 Jim_SetResultInt(interp
, options
.gmt
? timegm(&tm
) : mktime(&tm
));
158 static int clock_cmd_seconds(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
160 Jim_SetResultInt(interp
, time(NULL
));
165 static int clock_cmd_micros(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
169 gettimeofday(&tv
, NULL
);
171 Jim_SetResultInt(interp
, (jim_wide
) tv
.tv_sec
* 1000000 + tv
.tv_usec
);
176 static int clock_cmd_millis(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
180 gettimeofday(&tv
, NULL
);
182 Jim_SetResultInt(interp
, (jim_wide
) tv
.tv_sec
* 1000 + tv
.tv_usec
/ 1000);
187 static const jim_subcmd_type clock_command_table
[] = {
193 /* Description: Returns the current time in 'clicks' */
196 "seconds ?-format string? ?-gmt boolean?",
200 /* Description: Format the given time */
207 /* Description: Returns the current time in microseconds */
214 /* Description: Returns the current time in milliseconds */
218 "str -format format ?-gmt boolean?",
222 /* Description: Determine the time according to the given format */
230 /* Description: Returns the current time as seconds since the epoch */
235 int Jim_clockInit(Jim_Interp
*interp
)
237 if (Jim_PackageProvide(interp
, "clock", "1.0", JIM_ERRMSG
))
240 Jim_CreateCommand(interp
, "clock", Jim_SubCmdProc
, (void *)clock_command_table
, NULL
);