From: Igor Sysoev Date: Thu, 1 Sep 2016 13:12:31 +0000 (+0300) Subject: Now Date.parse() and Date() accept shortcut date strings. X-Git-Tag: 0.1.2~3 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=ee056a129cfd03f2305981c3ee79fccc74d368a3;p=njs.git Now Date.parse() and Date() accept shortcut date strings. --- diff --git a/njs/njs_date.c b/njs/njs_date.c index 93b5c81d..1ae2fee3 100644 --- a/njs/njs_date.c +++ b/njs/njs_date.c @@ -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 *args, nxt_uint_t nargs, 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,53 +429,34 @@ 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; - p = njs_date_skip_spaces(p, end); - if (nxt_slow_path(p == NULL)) { - return NJS_NAN; - } + for ( ;; ) { + next = njs_date_number_parse(&tm.tm_mday, p, end, 2); - 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; + 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 (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; - } + if (tm.tm_mon >= 0) { + /* Date.toString() format: "Mon Sep 28 1970 12:00:00 GMT+0600". */ - p = njs_date_number_parse(&tm.tm_year, p, end, 4); - if (nxt_slow_path(p == NULL)) { - return NJS_NAN; + return njs_date_js_string_parse(&tm, p + 3, end); } - tm.tm_year -= 1900; - - p = njs_date_skip_spaces(p, end); - if (nxt_slow_path(p == NULL)) { + if (!week) { return NJS_NAN; } - p = njs_date_time_parse(&tm, p, end); + p = njs_date_skip_week_day(p, end); if (nxt_slow_path(p == NULL)) { return NJS_NAN; } @@ -455,30 +466,31 @@ njs_date_string_parse(njs_value_t *date) return NJS_NAN; } - if (p + 2 < end) { + week = 0; + } - if ((p[0] == 'G' && p[1] == 'M' && p[2] == 'T') - || (p[0] == 'U' && p[1] == 'T' && p[2] == 'C')) - { - gmtoff = 0; +year: - } else { - gmtoff = njs_date_gmtoff_parse(p, end); - if (nxt_slow_path(gmtoff == -1)) { - return NJS_NAN; - } - } + tm.tm_year -= 1900; + +done: + + return njs_timegm(&tm) * 1000; +} - return (njs_timegm(&tm) - gmtoff * 60) * 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; } - /* 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,29 +499,80 @@ 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; } + 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; } - p = njs_date_number_parse(&tm.tm_year, p, end, 4); + if (p == end) { + goto done; + } + + p = njs_date_time_parse(tm, p, end); 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; + } + + 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_time_parse(&tm, p, end); + p = njs_date_number_parse(&tm->tm_mday, p, end, 2); if (nxt_slow_path(p == NULL)) { return NJS_NAN; } @@ -519,16 +582,58 @@ njs_date_string_parse(njs_value_t *date) 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_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, const u_char *end) p++; } + + return p; } return NULL; @@ -670,7 +777,11 @@ njs_date_time_parse(struct tm *tm, const u_char *p, const u_char *end) return p; } - if (nxt_slow_path(p >= end || *p != ':')) { + if (p == end) { + return p; + } + + if (nxt_slow_path(*p != ':')) { return NULL; } diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 69d6f29a..5714ebf0 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -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") },