details: http://hg.nginx.org/njs/rev/19758fdcd554 branches: changeset: 168:19758fdcd554 user: Igor Sysoev <i...@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") }, _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel