mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
Add date builtins (fix #364)
Windows support for strptime() is missing. We can add a copy of one from a BSD later.
This commit is contained in:
73
builtin.c
73
builtin.c
@@ -1,4 +1,6 @@
|
||||
#define _XOPEN_SOURCE
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#ifdef HAVE_ONIGURUMA
|
||||
@@ -6,6 +8,7 @@
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "builtin.h"
|
||||
#include "compile.h"
|
||||
#include "jq_parser.h"
|
||||
@@ -912,6 +915,74 @@ static jv f_stderr(jq_state *jq, jv input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
#ifdef HAVE_STRPTIME
|
||||
static jv f_strptime(jq_state *jq, jv a, jv b) {
|
||||
if (jv_get_kind(a) != JV_KIND_STRING || jv_get_kind(b) != JV_KIND_STRING)
|
||||
return jv_invalid_with_msg(jv_string("strptime/2 requires string inputs and arguments"));
|
||||
|
||||
struct tm tm;
|
||||
const char *input = jv_string_value(a);
|
||||
const char *fmt = jv_string_value(b);
|
||||
const char *end = strptime(input, fmt, &tm);
|
||||
|
||||
if (end == NULL || (*end != '\0' && !isspace(*end))) {
|
||||
jv e = jv_invalid_with_msg(jv_string_fmt("date \"%s\" does not match format \"%s\"", input, fmt));
|
||||
jv_free(a);
|
||||
jv_free(b);
|
||||
return e;
|
||||
}
|
||||
jv_free(a);
|
||||
jv_free(b);
|
||||
jv r = JV_ARRAY(jv_number(tm.tm_year + 1900),
|
||||
jv_number(tm.tm_mon),
|
||||
jv_number(tm.tm_mday),
|
||||
jv_number(tm.tm_hour),
|
||||
jv_number(tm.tm_min),
|
||||
jv_number(tm.tm_sec),
|
||||
jv_number(tm.tm_wday),
|
||||
jv_number(tm.tm_yday));
|
||||
if (*end != '\0')
|
||||
r = jv_array_append(r, jv_string(end));
|
||||
return r;
|
||||
}
|
||||
#else
|
||||
static jv f_strptime(jq_state *jq, jv a, jv b) {
|
||||
return jv_invalid_with_msg(jv_string("strptime/2 not implemented on this platform"));
|
||||
}
|
||||
#endif
|
||||
|
||||
#define TO_TM_FIELD(t, j, i, k) \
|
||||
do { \
|
||||
jv n = jv_array_get(jv_copy(j), (i)); \
|
||||
if (jv_get_kind(n) != (k)) \
|
||||
return jv_invalid_with_msg(jv_string("mktime() requires a 'gmtime' input (an array inputs of 8 numeric values)")); \
|
||||
t = jv_number_value(n); \
|
||||
jv_free(n); \
|
||||
} while (0)
|
||||
|
||||
static jv f_mktime(jq_state *jq, jv a) {
|
||||
if (jv_get_kind(a) != JV_KIND_ARRAY)
|
||||
return jv_invalid_with_msg(jv_string("mktime() requires array inputs"));
|
||||
if (jv_array_length(jv_copy(a)) < 6)
|
||||
return jv_invalid_with_msg(jv_string("mktime() requires a 'gmtime' input (an array inputs of 8 numeric values)"));
|
||||
struct tm tm;
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
TO_TM_FIELD(tm.tm_year, a, 0, JV_KIND_NUMBER);
|
||||
TO_TM_FIELD(tm.tm_mon, a, 1, JV_KIND_NUMBER);
|
||||
TO_TM_FIELD(tm.tm_mday, a, 2, JV_KIND_NUMBER);
|
||||
TO_TM_FIELD(tm.tm_hour, a, 3, JV_KIND_NUMBER);
|
||||
TO_TM_FIELD(tm.tm_min, a, 4, JV_KIND_NUMBER);
|
||||
TO_TM_FIELD(tm.tm_sec, a, 5, JV_KIND_NUMBER);
|
||||
tm.tm_year -= 1900;
|
||||
jv_free(a);
|
||||
time_t t = mktime(&tm);
|
||||
if (t == (time_t)-1)
|
||||
return jv_invalid_with_msg(jv_string("invalid gmtime representation"));
|
||||
return jv_number(t);
|
||||
}
|
||||
|
||||
#undef TO_TM_FIELD
|
||||
|
||||
|
||||
#define LIBM_DD(name) \
|
||||
{(cfunction_ptr)f_ ## name, "_" #name, 1},
|
||||
@@ -971,6 +1042,8 @@ static const struct cfunction function_list[] = {
|
||||
{(cfunction_ptr)f_input, "_input", 1},
|
||||
{(cfunction_ptr)f_debug, "debug", 1},
|
||||
{(cfunction_ptr)f_stderr, "stderr", 1},
|
||||
{(cfunction_ptr)f_strptime, "strptime", 2},
|
||||
{(cfunction_ptr)f_mktime, "mktime", 1},
|
||||
};
|
||||
#undef LIBM_DD
|
||||
|
||||
|
@@ -115,6 +115,7 @@ AM_CONDITIONAL([ENABLE_DOCS], [test "x$enable_docs" != xno])
|
||||
|
||||
AC_FIND_FUNC([isatty], [c], [#include <unistd.h>], [0])
|
||||
AC_FIND_FUNC([_isatty], [c], [#include <io.h>], [0])
|
||||
AC_FIND_FUNC([strptime], [c], [#include <time.h>], [0])
|
||||
|
||||
AC_ARG_ENABLE([pthread-tls],
|
||||
[AC_HELP_STRING([--enable-pthread-tls],
|
||||
|
@@ -1591,6 +1591,28 @@ sections:
|
||||
input: "\"O'Hara's Ale\""
|
||||
output: ["\"echo 'O'\\\\''Hara'\\\\''s Ale'\""]
|
||||
|
||||
- title: "Dates"
|
||||
body: |
|
||||
|
||||
The `strptime(fmt)` function parses input strings matching the
|
||||
`fmt` argument. The output is an array of eight numbers: the
|
||||
year, the month, the day of the month, the hour of the day,
|
||||
the minute of the hour, the second of the minute, the day of
|
||||
the week, and the day of the year, all zero-based except for
|
||||
the year and the month, which are one-based.
|
||||
|
||||
The `mktime` function consumes outputs from `strptime/1` and
|
||||
produces the time in seconds since the Unix epoch.
|
||||
|
||||
examples:
|
||||
- program: 'strptime'
|
||||
input: '"2015-03-05 23:51:47Z"'
|
||||
output: ['[2015,2,5,23,51,47,4,63]']
|
||||
|
||||
- program: 'strptime|mktime'
|
||||
input: '"2015-03-05 23:51:47Z"'
|
||||
output: ['1425621107']
|
||||
|
||||
- title: Conditionals and Comparisons
|
||||
entries:
|
||||
- title: "`==`, `!=`"
|
||||
|
6
jv.h
6
jv.h
@@ -87,9 +87,11 @@ jv jv_array_indexes(jv, jv);
|
||||
#define JV_ARRAY_5(e1,e2,e3,e4,e5) (jv_array_append(JV_ARRAY_4(e1,e2,e3,e4),e5))
|
||||
#define JV_ARRAY_6(e1,e2,e3,e4,e5,e6) (jv_array_append(JV_ARRAY_5(e1,e2,e3,e4,e5),e6))
|
||||
#define JV_ARRAY_7(e1,e2,e3,e4,e5,e6,e7) (jv_array_append(JV_ARRAY_6(e1,e2,e3,e4,e5,e6),e7))
|
||||
#define JV_ARRAY_IDX(_1,_2,_3,_4,_5,_6,_7,NAME,...) NAME
|
||||
#define JV_ARRAY_8(e1,e2,e3,e4,e5,e6,e7,e8) (jv_array_append(JV_ARRAY_7(e1,e2,e3,e4,e5,e6,e7),e8))
|
||||
#define JV_ARRAY_9(e1,e2,e3,e4,e5,e6,e7,e8,e9) (jv_array_append(JV_ARRAY_8(e1,e2,e3,e4,e5,e6,e7,e8),e9))
|
||||
#define JV_ARRAY_IDX(_1,_2,_3,_4,_5,_6,_7,_8,_9,NAME,...) NAME
|
||||
#define JV_ARRAY(...) \
|
||||
JV_ARRAY_IDX(__VA_ARGS__, JV_ARRAY_7, JV_ARRAY_6, JV_ARRAY_5, JV_ARRAY_4, JV_ARRAY_3, JV_ARRAY_2, JV_ARRAY_1)(__VA_ARGS__)
|
||||
JV_ARRAY_IDX(__VA_ARGS__, JV_ARRAY_9, JV_ARRAY_8, JV_ARRAY_7, JV_ARRAY_6, JV_ARRAY_5, JV_ARRAY_4, JV_ARRAY_3, JV_ARRAY_2, JV_ARRAY_1)(__VA_ARGS__)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define JV_PRINTF_LIKE(fmt_arg_num, args_num) \
|
||||
|
@@ -1140,6 +1140,10 @@ bsearch(4)
|
||||
[1,2,3]
|
||||
-4
|
||||
|
||||
[strptime("%Y-%m-%d %H:%M:%SZ")|(.,mktime)]
|
||||
"2015-03-05 23:51:47Z"
|
||||
[[2015,2,5,23,51,47,4,63],1425621107]
|
||||
|
||||
# module system
|
||||
import "a" as foo; import "b" as bar; def fooa: foo::a; [fooa, bar::a, bar::b, foo::a]
|
||||
null
|
||||
|
Reference in New Issue
Block a user