[njs] Fixed Date.parse() with ISO-8601 format and UTC time offset.
Dmitry Volyntsev
xeioex at nginx.com
Tue Jun 13 05:05:15 UTC 2023
details: https://hg.nginx.org/njs/rev/ed4ff34dfc63
branches:
changeset: 2154:ed4ff34dfc63
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Mon Jun 12 22:04:04 2023 -0700
description:
Fixed Date.parse() with ISO-8601 format and UTC time offset.
diffstat:
src/njs_date.c | 65 +++++++++++++++++++++++++++++++++++++++--------
src/test/njs_unit_test.c | 48 +++++++++++++++++++++++++++++++++++
2 files changed, 102 insertions(+), 11 deletions(-)
diffs (162 lines):
diff -r 803a5061b362 -r ed4ff34dfc63 src/njs_date.c
--- a/src/njs_date.c Mon Jun 12 20:51:54 2023 -0700
+++ b/src/njs_date.c Mon Jun 12 22:04:04 2023 -0700
@@ -493,11 +493,44 @@ njs_date_parse(njs_vm_t *vm, njs_value_t
}
+static int64_t
+njs_date_utc_offset_parse(const u_char *start, const u_char *end)
+{
+ int64_t utc_off, hour, min;
+ const u_char *p;
+
+ if (njs_fast_path(start + 2 < end && (*start == '+' || *start == '-'))) {
+ p = njs_date_number_parse(&hour, start + 1, end, 2);
+ if (njs_slow_path(p == NULL || hour > 23)) {
+ return -1;
+ }
+
+ if (p < end && *p == ':') {
+ p++;
+ }
+
+ p = njs_date_number_parse(&min, p, end, 2);
+ if (njs_slow_path(p == NULL || min > 59)) {
+ return -1;
+ }
+
+ utc_off = hour * 60 + min;
+
+ if (*start == '-') {
+ utc_off = -utc_off;
+ }
+
+ return utc_off;
+ }
+
+ return -1;
+}
+
static double
njs_date_string_parse(njs_value_t *date)
{
size_t ms_length;
- int64_t ext, skipped;
+ int64_t ext, utc_off;
njs_str_t string;
njs_bool_t sign, week, utc;
const u_char *p, *next, *end;
@@ -616,25 +649,37 @@ njs_date_string_parse(njs_value_t *date)
p++;
- ms_length = (end - p < 3) ? end - p : 3;
+ for (ms_length = 0; p + ms_length < end; ms_length++) {
+ if (p[ms_length] < '0' || p[ms_length] > '9') {
+ break;
+ }
+ }
p = njs_date_number_parse(&tm[NJS_DATE_MSEC], p, end, ms_length);
if (njs_slow_path(p == NULL)) {
return NAN;
}
- if (end > p) {
- p = njs_date_number_parse(&skipped, p, end, end - p);
- if (njs_slow_path(p == NULL)) {
- return NAN;
- }
- }
-
if (ms_length == 1) {
tm[NJS_DATE_MSEC] *= 100;
} else if (ms_length == 2) {
tm[NJS_DATE_MSEC] *= 10;
+
+ } else if (ms_length >= 4) {
+ for (ms_length -= 3; ms_length > 0; ms_length--) {
+ tm[NJS_DATE_MSEC] /= 10;
+ }
+ }
+
+ if (p < end) {
+ utc_off = njs_date_utc_offset_parse(p, end);
+ if (njs_slow_path(utc_off == -1)) {
+ return NAN;
+ }
+
+ utc = 1;
+ tm[NJS_DATE_MSEC] += -utc_off * 60000;
}
done:
@@ -685,8 +730,6 @@ done:
week = 0;
}
-
- return njs_make_date(tm, 0);
}
diff -r 803a5061b362 -r ed4ff34dfc63 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Mon Jun 12 20:51:54 2023 -0700
+++ b/src/test/njs_unit_test.c Mon Jun 12 22:04:04 2023 -0700
@@ -16172,6 +16172,54 @@ static njs_unit_test_t njs_test[] =
{ njs_str("Date.parse('2011-06-24T06:01:02.625Z')"),
njs_str("1308895262625") },
+ { njs_str("Date.parse('2011-06-24T06:01:02.625+00:00')"),
+ njs_str("1308895262625") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625+0000')"),
+ njs_str("1308895262625") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625+00:0')"),
+ njs_str("NaN") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625+00:')"),
+ njs_str("NaN") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625+00')"),
+ njs_str("NaN") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625+0')"),
+ njs_str("NaN") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625+')"),
+ njs_str("NaN") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625-01:15')"),
+ njs_str("1308899762625") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625-01:60')"),
+ njs_str("NaN") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625-25:59')"),
+ njs_str("NaN") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625+01:15')"),
+ njs_str("1308890762625") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625-23:59')"),
+ njs_str("1308981602625") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625+23:59')"),
+ njs_str("1308808922625") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.6255Z')"),
+ njs_str("1308895262625") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.62555Z')"),
+ njs_str("1308895262625") },
+
+ { njs_str("Date.parse('2011-06-24T06:01:02.625555Z')"),
+ njs_str("1308895262625") },
+
{ njs_str("Date.parse('2011-06-24T06:01:02.6255555Z')"),
njs_str("1308895262625") },
More information about the nginx-devel
mailing list