[njs] Now Date.parse() and Date() accept shortcut date strings.
Igor Sysoev
igor at sysoev.ru
Thu Sep 1 13:12:58 UTC 2016
details: http://hg.nginx.org/njs/rev/19758fdcd554
branches:
changeset: 168:19758fdcd554
user: Igor Sysoev <igor at sysoev.ru>
date: Thu Sep 01 16:12:31 2016 +0300
description:
Now Date.parse() and Date() accept shortcut date strings.
diffstat:
njs/njs_date.c | 305 ++++++++++++++++++++++++++++++++--------------
njs/test/njs_unit_test.c | 39 ++++++
2 files changed, 247 insertions(+), 97 deletions(-)
diffs (487 lines):
diff -r af6c17324584 -r 19758fdcd554 njs/njs_date.c
--- a/njs/njs_date.c Thu Sep 01 13:28:44 2016 +0300
+++ b/njs/njs_date.c Thu Sep 01 16:12:31 2016 +0300
@@ -44,6 +44,10 @@
static nxt_noinline double njs_date_string_parse(njs_value_t *date);
+static double njs_date_rfc2822_string_parse(struct tm *tm, const u_char *p,
+ const u_char *end);
+static double njs_date_js_string_parse(struct tm *tm, const u_char *p,
+ const u_char *end);
static const u_char *njs_date_skip_week_day(const u_char *p, const u_char *end);
static const u_char *njs_date_skip_spaces(const u_char *p, const u_char *end);
static nxt_noinline nxt_int_t njs_date_month_parse(const u_char *p,
@@ -297,9 +301,9 @@ njs_date_parse(njs_vm_t *vm, njs_value_t
static nxt_noinline double
njs_date_string_parse(njs_value_t *date)
{
- int ext, ms, gmtoff;
+ int ext, ms;
struct tm tm;
- nxt_bool_t sign;
+ nxt_bool_t sign, week;
const u_char *p, *next, *end;
njs_string_prop_t string;
@@ -308,7 +312,7 @@ njs_date_string_parse(njs_value_t *date)
p = string.start;
end = p + string.size;
- if (nxt_slow_path(p + 10 >= end)) {
+ if (nxt_slow_path(p >= end)) {
return NJS_NAN;
}
@@ -324,11 +328,21 @@ njs_date_string_parse(njs_value_t *date)
sign = 0;
}
+ tm.tm_mon = 0;
+ tm.tm_mday = 1;
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+
next = njs_date_number_parse(&tm.tm_year, p, end, 4);
if (next != NULL) {
/* ISO-8601 format: "1970-09-28T06:00:00.000Z" */
+ if (next == end) {
+ goto year;
+ }
+
if (*next != '-') {
/* Extended ISO-8601 format: "+001970-09-28T06:00:00.000Z" */
@@ -347,6 +361,10 @@ njs_date_string_parse(njs_value_t *date)
tm.tm_year = -tm.tm_year;
}
+ if (next == end) {
+ goto year;
+ }
+
if (*next != '-') {
return NJS_NAN;
}
@@ -361,7 +379,11 @@ njs_date_string_parse(njs_value_t *date)
tm.tm_mon--;
- if (nxt_slow_path(p >= end || *p != '-')) {
+ if (p == end) {
+ goto done;
+ }
+
+ if (nxt_slow_path(*p != '-')) {
return NJS_NAN;
}
@@ -370,7 +392,11 @@ njs_date_string_parse(njs_value_t *date)
return NJS_NAN;
}
- if (nxt_slow_path(p >= end || *p != 'T')) {
+ if (p == end) {
+ goto done;
+ }
+
+ if (nxt_slow_path(*p != 'T')) {
return NJS_NAN;
}
@@ -379,6 +405,10 @@ njs_date_string_parse(njs_value_t *date)
return NJS_NAN;
}
+ if (p == end) {
+ goto done;
+ }
+
if (nxt_slow_path(p >= end || *p != '.')) {
return NJS_NAN;
}
@@ -399,86 +429,68 @@ njs_date_string_parse(njs_value_t *date)
return NJS_NAN;
}
- p = njs_date_skip_week_day(p, end);
- if (nxt_slow_path(p == NULL)) {
- return NJS_NAN;
+ week = 1;
+
+ for ( ;; ) {
+ next = njs_date_number_parse(&tm.tm_mday, p, end, 2);
+
+ if (next != NULL) {
+ /*
+ * RFC 2822 format:
+ * "Mon, 28 Sep 1970 06:00:00 GMT",
+ * "Mon, 28 Sep 1970 06:00:00 UTC",
+ * "Mon, 28 Sep 1970 12:00:00 +0600".
+ */
+ return njs_date_rfc2822_string_parse(&tm, next, end);
+ }
+
+ tm.tm_mon = njs_date_month_parse(p, end);
+
+ if (tm.tm_mon >= 0) {
+ /* Date.toString() format: "Mon Sep 28 1970 12:00:00 GMT+0600". */
+
+ return njs_date_js_string_parse(&tm, p + 3, end);
+ }
+
+ if (!week) {
+ return NJS_NAN;
+ }
+
+ p = njs_date_skip_week_day(p, end);
+ if (nxt_slow_path(p == NULL)) {
+ return NJS_NAN;
+ }
+
+ p = njs_date_skip_spaces(p, end);
+ if (nxt_slow_path(p == NULL)) {
+ return NJS_NAN;
+ }
+
+ week = 0;
}
+year:
+
+ tm.tm_year -= 1900;
+
+done:
+
+ return njs_timegm(&tm) * 1000;
+}
+
+
+static double
+njs_date_rfc2822_string_parse(struct tm *tm, const u_char *p, const u_char *end)
+{
+ int gmtoff;
+
p = njs_date_skip_spaces(p, end);
if (nxt_slow_path(p == NULL)) {
return NJS_NAN;
}
- next = njs_date_number_parse(&tm.tm_mday, p, end, 2);
-
- if (next != NULL) {
- /*
- * RFC 2822 format:
- * "Mon, 28 Sep 1970 06:00:00 GMT",
- * "Mon, 28 Sep 1970 06:00:00 UTC",
- * "Mon, 28 Sep 1970 12:00:00 +0600".
- */
- p = njs_date_skip_spaces(next, end);
- if (nxt_slow_path(p == NULL)) {
- return NJS_NAN;
- }
-
- tm.tm_mon = njs_date_month_parse(p, end);
- if (nxt_slow_path(tm.tm_mon < 0)) {
- return NJS_NAN;
- }
-
- p = njs_date_skip_spaces(p + 3, end);
- if (nxt_slow_path(p == NULL)) {
- return NJS_NAN;
- }
-
- p = njs_date_number_parse(&tm.tm_year, p, end, 4);
- if (nxt_slow_path(p == NULL)) {
- return NJS_NAN;
- }
-
- tm.tm_year -= 1900;
-
- p = njs_date_skip_spaces(p, end);
- if (nxt_slow_path(p == NULL)) {
- return NJS_NAN;
- }
-
- p = njs_date_time_parse(&tm, p, end);
- if (nxt_slow_path(p == NULL)) {
- return NJS_NAN;
- }
-
- p = njs_date_skip_spaces(p, end);
- if (nxt_slow_path(p == NULL)) {
- return NJS_NAN;
- }
-
- if (p + 2 < end) {
-
- if ((p[0] == 'G' && p[1] == 'M' && p[2] == 'T')
- || (p[0] == 'U' && p[1] == 'T' && p[2] == 'C'))
- {
- gmtoff = 0;
-
- } else {
- gmtoff = njs_date_gmtoff_parse(p, end);
- if (nxt_slow_path(gmtoff == -1)) {
- return NJS_NAN;
- }
- }
-
- return (njs_timegm(&tm) - gmtoff * 60) * 1000;
- }
-
- return NJS_NAN;
- }
-
- /* Date.toString() format: "Mon Sep 28 1970 12:00:00 GMT+0600". */
-
- tm.tm_mon = njs_date_month_parse(p, end);
- if (nxt_slow_path(tm.tm_mon < 0)) {
+ tm->tm_mon = njs_date_month_parse(p, end);
+ if (nxt_slow_path(tm->tm_mon < 0)) {
return NJS_NAN;
}
@@ -487,48 +499,141 @@ njs_date_string_parse(njs_value_t *date)
return NJS_NAN;
}
- p = njs_date_number_parse(&tm.tm_mday, p, end, 2);
+ p = njs_date_number_parse(&tm->tm_year, p, end, 4);
if (nxt_slow_path(p == NULL)) {
return NJS_NAN;
}
- p = njs_date_skip_spaces(p, end);
- if (nxt_slow_path(p == NULL)) {
- return NJS_NAN;
+ tm->tm_year -= 1900;
+
+ if (p == end) {
+ goto done;
}
- p = njs_date_number_parse(&tm.tm_year, p, end, 4);
- if (nxt_slow_path(p == NULL)) {
- return NJS_NAN;
- }
-
- tm.tm_year -= 1900;
-
p = njs_date_skip_spaces(p, end);
if (nxt_slow_path(p == NULL)) {
return NJS_NAN;
}
- p = njs_date_time_parse(&tm, p, end);
+ if (p == end) {
+ goto done;
+ }
+
+ p = njs_date_time_parse(tm, p, end);
if (nxt_slow_path(p == NULL)) {
return NJS_NAN;
}
+ if (p == end) {
+ goto done;
+ }
+
p = njs_date_skip_spaces(p, end);
if (nxt_slow_path(p == NULL)) {
return NJS_NAN;
}
- if (p + 2 < end && p[0] == 'G' && p[1] == 'M' && p[2] == 'T') {
-
- gmtoff = njs_date_gmtoff_parse(&p[3], end);
-
- if (nxt_fast_path(gmtoff != -1)) {
- return (njs_timegm(&tm) - gmtoff * 60) * 1000;
+ if (p == end) {
+ goto done;
+ }
+
+ if (nxt_slow_path(p + 2 >= end)) {
+ return NJS_NAN;
+ }
+
+ if ((p[0] == 'G' && p[1] == 'M' && p[2] == 'T')
+ || (p[0] == 'U' && p[1] == 'T' && p[2] == 'C'))
+ {
+ gmtoff = 0;
+
+ } else {
+ gmtoff = njs_date_gmtoff_parse(p, end);
+
+ if (nxt_slow_path(gmtoff == -1)) {
+ return NJS_NAN;
}
}
+ return (njs_timegm(tm) - gmtoff * 60) * 1000;
+
+done:
+
+ return njs_timegm(tm) * 1000;
+}
+
+
+static double
+njs_date_js_string_parse(struct tm *tm, const u_char *p, const u_char *end)
+{
+ int gmtoff;
+
+ p = njs_date_skip_spaces(p, end);
+ if (nxt_slow_path(p == NULL)) {
+ return NJS_NAN;
+ }
+
+ p = njs_date_number_parse(&tm->tm_mday, p, end, 2);
+ if (nxt_slow_path(p == NULL)) {
+ return NJS_NAN;
+ }
+
+ p = njs_date_skip_spaces(p, end);
+ if (nxt_slow_path(p == NULL)) {
+ return NJS_NAN;
+ }
+
+ p = njs_date_number_parse(&tm->tm_year, p, end, 4);
+ if (nxt_slow_path(p == NULL)) {
+ return NJS_NAN;
+ }
+
+ tm->tm_year -= 1900;
+
+ if (p == end) {
+ goto done;
+ }
+
+ p = njs_date_skip_spaces(p, end);
+ if (nxt_slow_path(p == NULL)) {
+ return NJS_NAN;
+ }
+
+ if (p == end) {
+ goto done;
+ }
+
+ p = njs_date_time_parse(tm, p, end);
+ if (nxt_slow_path(p == NULL)) {
+ return NJS_NAN;
+ }
+
+ if (p == end) {
+ goto done;
+ }
+
+ p = njs_date_skip_spaces(p, end);
+ if (nxt_slow_path(p == NULL)) {
+ return NJS_NAN;
+ }
+
+ if (p == end) {
+ goto done;
+ }
+
+ if (p + 2 < end && p[0] == 'G' && p[1] == 'M' && p[2] == 'T') {
+
+ gmtoff = njs_date_gmtoff_parse(&p[3], end);
+
+ if (nxt_fast_path(gmtoff != -1)) {
+ return (njs_timegm(tm) - gmtoff * 60) * 1000;
+ }
+ }
+
return NJS_NAN;
+
+done:
+
+ return njs_timegm(tm) * 1000;
}
@@ -559,6 +664,8 @@ njs_date_skip_spaces(const u_char *p, co
p++;
}
+
+ return p;
}
return NULL;
@@ -670,7 +777,11 @@ njs_date_time_parse(struct tm *tm, const
return p;
}
- if (nxt_slow_path(p >= end || *p != ':')) {
+ if (p == end) {
+ return p;
+ }
+
+ if (nxt_slow_path(*p != ':')) {
return NULL;
}
diff -r af6c17324584 -r 19758fdcd554 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Thu Sep 01 13:28:44 2016 +0300
+++ b/njs/test/njs_unit_test.c Thu Sep 01 16:12:31 2016 +0300
@@ -4515,15 +4515,54 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("Date.parse()"),
nxt_string("NaN") },
+ { nxt_string("Date.parse('2011')"),
+ nxt_string("1293840000000") },
+
+ { nxt_string("Date.parse('+002011')"),
+ nxt_string("1293840000000") },
+
+ { nxt_string("Date.parse('2011-06')"),
+ nxt_string("1306886400000") },
+
+ { nxt_string("Date.parse('2011-06-24')"),
+ nxt_string("1308873600000") },
+
+ { nxt_string("Date.parse('2011-06-24T06')"),
+ nxt_string("NaN") },
+
+ { nxt_string("Date.parse('2011-06-24T06:01')"),
+ nxt_string("1308895260000") },
+
+ { nxt_string("Date.parse('2011-06-24T06:01:02')"),
+ nxt_string("1308895262000") },
+
{ nxt_string("Date.parse('2011-06-24T06:01:02.625Z')"),
nxt_string("1308895262625") },
+ { nxt_string("Date.parse('24 Jun 2011')"),
+ nxt_string("1308873600000") },
+
+ { nxt_string("Date.parse('Fri, 24 Jun 2011 18:48')"),
+ nxt_string("1308941280000") },
+
+ { nxt_string("Date.parse('Fri, 24 Jun 2011 18:48:02')"),
+ nxt_string("1308941282000") },
+
{ nxt_string("Date.parse('Fri, 24 Jun 2011 18:48:02 GMT')"),
nxt_string("1308941282000") },
{ nxt_string("Date.parse('Fri, 24 Jun 2011 18:48:02 +1245')"),
nxt_string("1308895382000") },
+ { nxt_string("Date.parse('Jun 24 2011')"),
+ nxt_string("1308873600000") },
+
+ { nxt_string("Date.parse('Fri Jun 24 2011 18:48')"),
+ nxt_string("1308941280000") },
+
+ { nxt_string("Date.parse('Fri Jun 24 2011 18:48:02')"),
+ nxt_string("1308941282000") },
+
{ nxt_string("Date.parse('Fri Jun 24 2011 18:48:02 GMT+1245')"),
nxt_string("1308895382000") },
More information about the nginx-devel
mailing list