]> git.kaiwu.me - njs.git/commitdiff
Fixed parsing ISO 8601 format in Date.parse().
authorAndrey Zelenkov <zelenkov@nginx.com>
Wed, 19 Apr 2017 14:48:56 +0000 (17:48 +0300)
committerAndrey Zelenkov <zelenkov@nginx.com>
Wed, 19 Apr 2017 14:48:56 +0000 (17:48 +0300)
Fixed parsing in case milliseconds are not specified.
Added converting to local time in case "Z" suffix is not specified.
Also minor style fixes included.

njs/njs_date.c
njs/test/njs_unit_test.c

index 8d5bfe6d1815ce100ec4f18f4b15768839000d24..4136d1b4517fcb0596a2a8fc4cf76a493dec72bd 100644 (file)
@@ -304,9 +304,10 @@ 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;
+    int                ext, ms, ms_length, skipped;
+    double             time;
     struct tm          tm;
-    nxt_bool_t         sign, week;
+    nxt_bool_t         sign, week, utc;
     const u_char       *p, *next, *end;
     njs_string_prop_t  string;
 
@@ -319,11 +320,7 @@ njs_date_string_parse(njs_value_t *date)
         return NAN;
     }
 
-    if (*p == '+') {
-        p++;
-        sign = 1;
-
-    } else if (*p == '-') {
+    if (*p == '+' || *p == '-') {
         p++;
         sign = 1;
 
@@ -403,6 +400,14 @@ njs_date_string_parse(njs_value_t *date)
             return NAN;
         }
 
+        utc = 1;
+        end--;
+
+        if (*end != 'Z') {
+           utc = 0;
+           end++;
+        }
+
         p = njs_date_time_parse(&tm, p + 1, end);
         if (nxt_slow_path(p == NULL)) {
             return NAN;
@@ -412,20 +417,42 @@ njs_date_string_parse(njs_value_t *date)
             goto done;
         }
 
-        if (nxt_slow_path(p >= end || *p != '.')) {
+        if (nxt_slow_path(p > end || *p != '.')) {
             return NAN;
         }
 
-        p = njs_date_number_parse(&ms, p + 1, end, 3);
+        p++;
+
+        ms_length = (end - p < 3) ? end - p : 3;
+
+        p = njs_date_number_parse(&ms, p, end, ms_length);
         if (nxt_slow_path(p == NULL)) {
             return NAN;
         }
 
-        if (nxt_slow_path(p >= end || *p != 'Z')) {
-            return NAN;
+        if (end > p) {
+            p = njs_date_number_parse(&skipped, p, end, end - p);
+            if (nxt_slow_path(p == NULL)) {
+                return NAN;
+            }
+        }
+
+        if (ms_length == 1) {
+            ms *= 100;
+
+        } else if (ms_length == 2) {
+            ms *= 10;
+        }
+
+        if (utc) {
+            time = njs_timegm(&tm);
+
+        } else {
+            tm.tm_isdst = -1;
+            time = mktime(&tm);
         }
 
-        return njs_timegm(&tm) * 1000 + ms;
+        return time * 1000 + ms;
     }
 
     if (sign) {
index 4a5aaa7cdf638325961ec9890dde5dbe08a5f876..f6b38e46d294c429b20b1341aca902037b2da60a 100644 (file)
@@ -5713,15 +5713,47 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("Date.parse('2011-06-24T06')"),
       nxt_string("NaN") },
 
-    { nxt_string("Date.parse('2011-06-24T06:01')"),
+    { nxt_string("Date.parse('2011-06-24T06:')"),
+      nxt_string("NaN") },
+
+    { nxt_string("Date.parse('2011-06-24T06:01:')"),
+      nxt_string("NaN") },
+
+    { nxt_string("Date.parse('2011-06-24T06:01Z')"),
       nxt_string("1308895260000") },
 
-    { nxt_string("Date.parse('2011-06-24T06:01:02')"),
+    { nxt_string("Date.parse('2011-06-24T06:01:02:')"),
+      nxt_string("NaN") },
+
+    { nxt_string("Date.parse('2011-06-24T06:01:02Z')"),
       nxt_string("1308895262000") },
 
+    { nxt_string("Date.parse('2011-06-24T06:01:02.Z')"),
+      nxt_string("NaN") },
+
+    { nxt_string("Date.parse('2011-06-24T06:01:02.6Z')"),
+      nxt_string("1308895262600") },
+
+    { nxt_string("Date.parse('2011-06-24T06:01:02.62Z')"),
+      nxt_string("1308895262620") },
+
+    { nxt_string("Date.parse('2011-06-24T06:01:02:625Z')"),
+      nxt_string("NaN") },
+
     { nxt_string("Date.parse('2011-06-24T06:01:02.625Z')"),
       nxt_string("1308895262625") },
 
+    { nxt_string("Date.parse('2011-06-24T06:01:02.6255555Z')"),
+      nxt_string("1308895262625") },
+
+    { nxt_string("Date.parse('2011-06-24T06:01:02.625555Z5')"),
+      nxt_string("NaN") },
+
+    { nxt_string("var d = new Date(); var str = d.toISOString();"
+                 "var diff = Date.parse(str) - Date.parse(str.substring(0, str.length - 1));"
+                 "d.getTimezoneOffset() == -diff/1000/60"),
+      nxt_string("true") },
+
     { nxt_string("Date.parse('24 Jun 2011')"),
       nxt_string("1308873600000") },