[njs] Fixed Date() constructor according to specification.
Dmitry Volyntsev
xeioex at nginx.com
Thu Oct 10 17:54:28 UTC 2019
details: https://hg.nginx.org/njs/rev/eb57c1e27495
branches:
changeset: 1180:eb57c1e27495
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Thu Oct 10 20:54:03 2019 +0300
description:
Fixed Date() constructor according to specification.
diffstat:
src/njs_date.c | 71 +++++++++++++++++++++++++++++------------------
src/test/njs_unit_test.c | 29 +++++++++++++++++++
2 files changed, 73 insertions(+), 27 deletions(-)
diffs (186 lines):
diff -r 78371ab5c449 -r eb57c1e27495 src/njs_date.c
--- a/src/njs_date.c Wed Oct 09 14:43:09 2019 +0300
+++ b/src/njs_date.c Thu Oct 10 20:54:03 2019 +0300
@@ -139,9 +139,32 @@ njs_make_day(int64_t yr, int64_t month,
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_v
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_v
}
} 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_v
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_v
}
/* 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;
-
- time = (int64_t) mktime(&tm) * 1000 + values[7];
+ day = njs_make_day(values[1], values[2], values[3]);
+
+ tm = njs_make_time(values[4], values[5], values[6], values[7]);
+
+ time = njs_make_date(day, tm, 1);
}
done:
@@ -293,7 +315,7 @@ njs_date_utc(njs_vm_t *vm, njs_value_t *
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);
diff -r 78371ab5c449 -r eb57c1e27495 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Wed Oct 09 14:43:09 2019 +0300
+++ b/src/test/njs_unit_test.c Thu Oct 10 20:54:03 2019 +0300
@@ -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") },
More information about the nginx-devel
mailing list