diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp index 292fd1071..d5bc9d62d 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp @@ -726,6 +726,7 @@ ecma_date_make_day (ecma_number_t year, /**< year value */ ecma_number_t month, /**< month value */ ecma_number_t date) /**< date value */ { + /* 1. */ if (ecma_number_is_nan (year) || ecma_number_is_nan (month) || ecma_number_is_nan (date) @@ -736,25 +737,66 @@ ecma_date_make_day (ecma_number_t year, /**< year value */ return ecma_number_make_nan (); } + /* 2., 3., 4. */ ecma_number_t y = ecma_number_trunc (year); ecma_number_t m = ecma_number_trunc (month); ecma_number_t dt = ecma_number_trunc (date); + /* 5. */ ecma_number_t ym = y + (ecma_number_t) floor (m / 12); + /* 6. */ ecma_number_t mn = (ecma_number_t) fmod (m, 12); mn = (mn < 0) ? 12 + mn : mn; + + /* 7. */ ecma_number_t time = ecma_date_time_from_year (ym); + int32_t step = 182; + int32_t delta = step; - JERRY_ASSERT (ecma_date_year_from_time (time) == ym); - - while (ecma_date_month_from_time (time) < mn) + /** + * The algorithm below searches the following date: ym-mn-1 + * To find this time it starts from the beggining of the year (ym) + * then increase it by ECMA_DATE_MS_PER_DAY until it reaches the + * right date. + */ + if (ecma_date_year_from_time (time) == ym) { - time += ECMA_DATE_MS_PER_DAY; + /** + * Binary search to get the closest day in the previous month. + * It has to use integer days so sometimes the found time + * needs some more increasing which is done day by day below. + */ + while (delta) + { + if (ecma_date_month_from_time (time + step * ECMA_DATE_MS_PER_DAY) < mn) + { + step += delta; + } + else + { + step -= delta; + } + delta = delta / 2; + } + + if (ecma_date_month_from_time (time + step) < mn) + { + time += step * ECMA_DATE_MS_PER_DAY; + } + + /* Get the month's first day */ + while (ecma_date_month_from_time (time) < mn) + { + time += ECMA_DATE_MS_PER_DAY; + } + + if (ecma_date_month_from_time (time) == mn && ecma_date_date_from_time (time) == 1) + { + /* 8. */ + return ecma_date_day (time) + dt - ((ecma_number_t) 1.0); + } } - JERRY_ASSERT (ecma_date_month_from_time (time) == mn); - JERRY_ASSERT (ecma_date_date_from_time (time) == 1); - - return ecma_date_day (time) + dt - ((ecma_number_t) 1.0); + return ecma_number_make_nan (); } /* ecma_date_make_day */ /** diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h index a3cd4b96d..94ffbd2d2 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h @@ -56,13 +56,13 @@ extern ecma_completion_value_t ecma_builtin_helper_def_prop (ecma_object_t *obj_ * ECMA-262 v5, 15.9.1.1, 15.9.1.10 */ /* Hours in a day. */ -#define ECMA_DATE_HOURS_PER_DAY 24 +#define ECMA_DATE_HOURS_PER_DAY ((ecma_number_t) 24) /* Minutes in an hour. */ -#define ECMA_DATE_MINUTES_PER_HOUR 60 +#define ECMA_DATE_MINUTES_PER_HOUR ((ecma_number_t) 60) /* Seconds in a minute. */ -#define ECMA_DATE_SECONDS_PER_MINUTE 60 +#define ECMA_DATE_SECONDS_PER_MINUTE ((ecma_number_t) 60) /* Milliseconds in a second. */ -#define ECMA_DATE_MS_PER_SECOND 1000 +#define ECMA_DATE_MS_PER_SECOND ((ecma_number_t) 1000) /* ECMA_DATE_MS_PER_MINUTE == 60000 */ #define ECMA_DATE_MS_PER_MINUTE (ECMA_DATE_MS_PER_SECOND * ECMA_DATE_SECONDS_PER_MINUTE) /* ECMA_DATE_MS_PER_HOUR == 3600000 */ diff --git a/tests/jerry/date-construct.js b/tests/jerry/date-construct.js index 463a6e2e5..14b62dcb1 100644 --- a/tests/jerry/date-construct.js +++ b/tests/jerry/date-construct.js @@ -52,6 +52,12 @@ assert (d.valueOf() == 8.64e+15); d = new Date(8.64e+15 + 1); assert (isNaN(d.valueOf())); +d = new Date(20000000, 0, 1); +assert (isNaN(d.valueOf())); + +d = new Date(0, 20000000, 1); +assert (isNaN(d.valueOf())); + var Obj = function (val) { this.value = val;