[njs] Fixed parsing ISO 8601 format in Date.parse().

Andrey Zelenkov zelenkov at nginx.com
Wed Apr 19 14:51:45 UTC 2017


details:   http://hg.nginx.org/njs/rev/96fda9957427
branches:  
changeset: 340:96fda9957427
user:      Andrey Zelenkov <zelenkov at nginx.com>
date:      Wed Apr 19 17:48:56 2017 +0300
description:
Fixed parsing ISO 8601 format in Date.parse().

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.

diffstat:

 njs/njs_date.c           |  51 ++++++++++++++++++++++++++++++++++++-----------
 njs/test/njs_unit_test.c |  36 ++++++++++++++++++++++++++++++++-
 2 files changed, 73 insertions(+), 14 deletions(-)

diffs (145 lines):

diff -r 5a5b70cbbde9 -r 96fda9957427 njs/njs_date.c
--- a/njs/njs_date.c	Tue Apr 04 13:24:09 2017 +0300
+++ b/njs/njs_date.c	Wed Apr 19 17:48:56 2017 +0300
@@ -304,9 +304,10 @@ 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;
+    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;
+            }
         }
 
-        return njs_timegm(&tm) * 1000 + ms;
+        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 time * 1000 + ms;
     }
 
     if (sign) {
diff -r 5a5b70cbbde9 -r 96fda9957427 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c	Tue Apr 04 13:24:09 2017 +0300
+++ b/njs/test/njs_unit_test.c	Wed Apr 19 17:48:56 2017 +0300
@@ -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") },
 


More information about the nginx-devel mailing list