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,
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;
p = string.start;
end = p + string.size;
- if (nxt_slow_path(p + 10 >= end)) {
+ if (nxt_slow_path(p >= end)) {
return NJS_NAN;
}
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" */
tm.tm_year = -tm.tm_year;
}
+ if (next == end) {
+ goto year;
+ }
+
if (*next != '-') {
return NJS_NAN;
}
tm.tm_mon--;
- if (nxt_slow_path(p >= end || *p != '-')) {
+ if (p == end) {
+ goto done;
+ }
+
+ if (nxt_slow_path(*p != '-')) {
return NJS_NAN;
}
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;
}
return NJS_NAN;
}
+ if (p == end) {
+ goto done;
+ }
+
if (nxt_slow_path(p >= end || *p != '.')) {
return NJS_NAN;
}
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;
}
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;
}
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;
}
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;
}
p++;
}
+
+ return p;
}
return NULL;
return p;
}
- if (nxt_slow_path(p >= end || *p != ':')) {
+ if (p == end) {
+ return p;
+ }
+
+ if (nxt_slow_path(*p != ':')) {
return NULL;
}
{ 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") },