]> git.kaiwu.me - njs.git/commitdiff
Fixed Date() constructor according to specification.
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 10 Oct 2019 17:54:03 +0000 (20:54 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Thu, 10 Oct 2019 17:54:03 +0000 (20:54 +0300)
src/njs_date.c
src/test/njs_unit_test.c

index 25b0a361a29966e20132a34093c7e33d2b3c1923..4eacbe26866cc4c506c1ad681de00fabefd2bd77 100644 (file)
@@ -139,9 +139,32 @@ njs_make_day(int64_t yr, int64_t month, int64_t date)
 
 
 njs_inline int64_t
-njs_make_date(int64_t days, int64_t time)
+njs_tz_offset(int64_t time)
 {
-    return days * 86400000 + time;
+    time_t     ti;
+    struct tm  tm;
+
+    time /= 1000;
+
+    ti = time;
+    localtime_r(&ti, &tm);
+
+    return -njs_timezone(&tm) / 60;
+}
+
+
+njs_inline int64_t
+njs_make_date(int64_t days, int64_t time, njs_bool_t local)
+{
+    int64_t  date;
+
+    date = days * 86400000 + time;
+
+    if (local) {
+        date += njs_tz_offset(date) * 60000;
+    }
+
+    return date;
 }
 
 
@@ -150,11 +173,11 @@ njs_date_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_index_t unused)
 {
     double      num, time;
-    int64_t     values[8];
+    int64_t     day, tm;
     njs_int_t   ret;
     njs_uint_t  i, n;
     njs_date_t  *date;
-    struct tm   tm;
+    int64_t     values[8];
 
     if (vm->top_frame->ctor) {
 
@@ -182,9 +205,13 @@ njs_date_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
             }
 
         } else {
+
+            time = NAN;
+
             njs_memzero(values, 8 * sizeof(int64_t));
-            /* Month. */
-            values[2] = 1;
+
+            /* Day. */
+            values[3] = 1;
 
             n = njs_min(8, nargs);
 
@@ -198,8 +225,7 @@ njs_date_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
 
                 num = njs_number(&args[i]);
 
-                if (isnan(num)) {
-                    time = num;
+                if (isnan(num) || isinf(num)) {
                     goto done;
                 }
 
@@ -207,19 +233,15 @@ njs_date_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
             }
 
             /* Year. */
-            if (values[1] > 99) {
-                values[1] -= 1900;
+            if (values[1] >= 0 && values[1] < 100) {
+                values[1] += 1900;
             }
 
-            tm.tm_year = values[1];
-            tm.tm_mon = values[2];
-            tm.tm_mday = values[3];
-            tm.tm_hour = values[4];
-            tm.tm_min = values[5];
-            tm.tm_sec = values[6];
-            tm.tm_isdst = -1;
+            day = njs_make_day(values[1], values[2], values[3]);
+
+            tm = njs_make_time(values[4], values[5], values[6], values[7]);
 
-            time = (int64_t) mktime(&tm) * 1000 + values[7];
+            time = njs_make_date(day, tm, 1);
         }
 
     done:
@@ -293,7 +315,7 @@ njs_date_utc(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
         day = njs_make_day(values[1], values[2], values[3]);
         tm = njs_make_time(values[4], values[5], values[6], values[7]);
 
-        time = njs_timeclip(njs_make_date(day, tm));
+        time = njs_timeclip(njs_make_date(day, tm, 0));
     }
 
 done:
@@ -1478,17 +1500,12 @@ static njs_int_t
 njs_date_prototype_get_timezone_offset(njs_vm_t *vm, njs_value_t *args,
     njs_uint_t nargs, njs_index_t unused)
 {
-    double     value;
-    time_t     clock;
-    struct tm  tm;
+    double  value;
 
     value = njs_date(&args[0])->time;
 
     if (njs_fast_path(!isnan(value))) {
-        clock = value / 1000;
-        localtime_r(&clock, &tm);
-
-        value = - njs_timezone(&tm) / 60;
+        value = njs_tz_offset(value);
     }
 
     njs_set_number(&vm->retval, value);
index d91fbe9ffe47593a01b5d67ec627a901c4ab639f..0de5d5292db5bf5dfc28a855a5ccda0877f2118d 100644 (file)
@@ -11606,6 +11606,11 @@ static njs_unit_test_t  njs_test[] =
                  "d.toISOString()"),
       njs_str("2011-06-24T18:45:12.625Z") },
 
+    { njs_str("var d = new Date(1999, 9, 10, 10, 10, 10, 10);"
+              "var local = new Date(d.getTime() - d.getTimezoneOffset() * 60000);"
+              "local.toISOString()"),
+      njs_str("1999-10-10T10:10:10.010Z") },
+
 #if 0
     /* These tests fail on Solaris: gmtime_r() returns off by one day. */
 
@@ -11790,12 +11795,36 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("var n = Date.now(); n == new Date(n)"),
       njs_str("true") },
 
+    { njs_str("var d = new Date(2011,0); d.getFullYear()"),
+      njs_str("2011") },
+
+    { njs_str("var d = new Date(2011, 0, 1, 0, 0, 0, -1); d.getFullYear()"),
+      njs_str("2010") },
+
+    { njs_str("var d = new Date(2011, 11, 31, 23, 59, 59, 999); d.getFullYear()"),
+      njs_str("2011") },
+
+    { njs_str("var d = new Date(2011, 11, 31, 23, 59, 59, 1000); d.getFullYear()"),
+      njs_str("2012") },
+
     { njs_str("var d = new Date(2011, 5, 24, 18, 45); d.getFullYear()"),
       njs_str("2011") },
 
     { njs_str("var d = new Date(2011, 5, 24, 18, 45); d.getUTCFullYear()"),
       njs_str("2011") },
 
+    { njs_str("var d = new Date(2011, 5); d.getMonth()"),
+      njs_str("5") },
+
+    { njs_str("var d = new Date(2011, 6, 0, 0, 0, 0, -1); d.getMonth()"),
+      njs_str("5") },
+
+    { njs_str("var d = new Date(2011, 6, 31, 23, 59, 59, 999); d.getMonth()"),
+      njs_str("6") },
+
+    { njs_str("var d = new Date(2011, 6, 31, 23, 59, 59, 1000); d.getMonth()"),
+      njs_str("7") },
+
     { njs_str("var d = new Date(2011, 5, 24, 18, 45); d.getMonth()"),
       njs_str("5") },