diff options
author | Zoltan Herczeg <zherczeg.u-szeged@partner.samsung.com> | 2017-01-11 08:27:29 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-11 08:27:29 +0100 |
commit | 7d83293762aa36b14f1b697d05ab4aa462a83f31 (patch) | |
tree | 77aa9476700517f8ce61db1314d8a206e2705e9b /jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c | |
parent | 00b220bde675c363659a9d3c22f5d37e4409807e (diff) |
Improve date helpers. (#1499)
Rework date to string conversion, and remove nan checks from inline
functions. Furtermore some inline functions are changed to normal
functions.
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
Diffstat (limited to 'jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c')
-rw-r--r-- | jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c | 968 |
1 files changed, 301 insertions, 667 deletions
diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c index 47758b00..c79af7b1 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c @@ -39,25 +39,12 @@ * See also: * ECMA-262 v5, 15.9.1.2 * - * Used by: - * - The Date.prototype.setMilliseconds routine. - * - The Date.prototype.setUTCMilliseconds routine. - * - The Date.prototype.setSeconds routine. - * - The Date.prototype.setUTCSeconds routine. - * - The Date.prototype.setMinutes routine. - * - The Date.prototype.setUTCMinutes routine. - * - The Date.prototype.setHours routine. - * - The Date.prototype.setUTCHours routine. - * - * @return time value for day number + * @return time value for day number */ inline ecma_number_t __attr_always_inline___ ecma_date_day (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) - { - return time; /* time is NaN */ - } + JERRY_ASSERT (!ecma_number_is_nan (time)); return (ecma_number_t) floor (time / ECMA_DATE_MS_PER_DAY); } /* ecma_date_day */ @@ -68,76 +55,28 @@ ecma_date_day (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.2 * - * Used by: - * - The Date.prototype.setDate routine. - * - The Date.prototype.setUTCDate routine. - * - The Date.prototype.setMonth routine. - * - The Date.prototype.setUTCMonth routine. - * - The Date.prototype.setFullYear routine. - * - The Date.prototype.setUTCFullYear routine. - * - * @return time value within the day + * @return time value within the day */ inline ecma_number_t __attr_always_inline___ ecma_date_time_within_day (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) - { - return time; /* time is NaN */ - } + JERRY_ASSERT (!ecma_number_is_nan (time)); return (ecma_number_t) fmod (time, ECMA_DATE_MS_PER_DAY); } /* ecma_date_time_within_day */ /** - * Helper function to get number of days from year value. - * - * See also: - * ECMA-262 v5, 15.9.1.3 - * - * @return number of days - */ -inline ecma_number_t __attr_always_inline___ -ecma_date_days_in_year (ecma_number_t year) /**< year value */ -{ - if (ecma_number_is_nan (year)) - { - return year; /* year is NaN */ - } - - if (fmod (floor (year), 4) != ECMA_NUMBER_ZERO) - { - return (ecma_number_t) 365; - } - - if (fmod (floor (year), 100) != ECMA_NUMBER_ZERO) - { - return (ecma_number_t) 366; - } - - if (fmod (floor (year), 400) != ECMA_NUMBER_ZERO) - { - return (ecma_number_t) 365; - } - - return (ecma_number_t) 366; -} /* ecma_date_days_in_year */ - -/** * Helper function to get the day number of the first day of a year. * * See also: * ECMA-262 v5, 15.9.1.3 * - * @return day number of the first day of a year + * @return day number of the first day of a year */ -inline ecma_number_t __attr_always_inline___ +static ecma_number_t ecma_date_day_from_year (ecma_number_t year) /**< year value */ { - if (ecma_number_is_nan (year)) - { - return year; /* year is NaN */ - } + JERRY_ASSERT (!ecma_number_is_nan (year)); return (ecma_number_t) (365 * (year - 1970) + floor ((year - 1969) / 4) @@ -153,13 +92,10 @@ ecma_date_day_from_year (ecma_number_t year) /**< year value */ * * @return time value of the start of a year */ -inline ecma_number_t __attr_always_inline___ +static inline ecma_number_t __attr_always_inline___ ecma_date_time_from_year (ecma_number_t year) /**< year value */ { - if (ecma_number_is_nan (year)) - { - return year; /* year is NaN */ - } + JERRY_ASSERT (!ecma_number_is_nan (year)); return ECMA_DATE_MS_PER_DAY * ecma_date_day_from_year (year); } /* ecma_date_time_from_year */ @@ -170,23 +106,12 @@ ecma_date_time_from_year (ecma_number_t year) /**< year value */ * See also: * ECMA-262 v5, 15.9.1.3 * - * Used by: - * - The Date.prototype.getFullYear routine. (Generated.) - * - The Date.prototype.getUTCFullYear routine. (Generated.) - * - The Date.prototype.setDate routine. - * - The Date.prototype.setUTCDate routine. - * - The Date.prototype.setMonth routine. - * - The Date.prototype.setUTCMonth routine. - * - * @return year value + * @return year value */ ecma_number_t ecma_date_year_from_time (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) - { - return time; /* time is NaN */ - } + JERRY_ASSERT (!ecma_number_is_nan (time)); /* ECMA-262 v5, 15.9.1.1 define the largest year that is * representable (285616) forward from 01 January, 1970 UTC. @@ -205,6 +130,7 @@ ecma_date_year_from_time (ecma_number_t time) /**< time value */ { lower_year_boundary = year_boundary; } + year--; } @@ -217,37 +143,41 @@ ecma_date_year_from_time (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.3 * - * @return 1 if time within a leap year and otherwise is zero + * @return 1 if time within a leap year + * 0 otherwise */ -inline ecma_number_t __attr_always_inline___ -ecma_date_in_leap_year (ecma_number_t time) /**< time value */ +static int +ecma_date_in_leap_year (ecma_number_t year) /**< time value */ { - if (ecma_number_is_nan (time)) + int mod_400 = (int) fmod (floor (year), 400); + + JERRY_ASSERT (mod_400 >= -399 && mod_400 <= 399); + + if ((mod_400 % 4) != 0) { - return time; /* time is NaN */ + return 0; } - return ecma_date_days_in_year (ecma_date_year_from_time (time)) - 365; + if ((mod_400 % 100) != 0) + { + return 1; + } + + if (mod_400 != 0) + { + return 0; + } + + return 1; } /* ecma_date_in_leap_year */ /** - * Helper function to get day within year from time value. - * - * See also: - * ECMA-262 v5, 15.9.1.4 - * - * @return number of days within year + * End day for the first 11 months. */ -inline ecma_number_t __attr_always_inline___ -ecma_date_day_within_year (ecma_number_t time) /**< time value */ +static const int16_t ecma_date_month_end_day[10] = { - if (ecma_number_is_nan (time)) - { - return time; /* time is NaN */ - } - - return ecma_date_day (time) - ecma_date_day_from_year (ecma_date_year_from_time (time)); -} /* ecma_date_day_within_year */ + 58, 89, 119, 150, 180, 211, 242, 272, 303, 333 +}; /** * Helper function to get month from time value. @@ -255,72 +185,33 @@ ecma_date_day_within_year (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.4 * - * Used by: - * - The Date.prototype.getMonth routine. (Generated.) - * - The Date.prototype.getUTCMonth routine. (Generated.) - * - The Date.prototype.setDate routine. - * - The Date.prototype.setUTCDate routine. - * - The Date.prototype.setFullYear routine. - * - The Date.prototype.setUTCFullYear routine. - * - * @return month number + * @return month number */ ecma_number_t ecma_date_month_from_time (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) - { - return time; /* time is NaN */ - } + JERRY_ASSERT (!ecma_number_is_nan (time)); - ecma_number_t in_leap_year = ecma_date_in_leap_year (time); - ecma_number_t day_within_year = ecma_date_day_within_year (time); + ecma_number_t year = ecma_date_year_from_time (time); + int day_within_year = (int) (ecma_date_day (time) - ecma_date_day_from_year (year)); - JERRY_ASSERT (day_within_year >= 0 && day_within_year < 365 + in_leap_year); + JERRY_ASSERT (day_within_year >= 0); - if (day_within_year < 31) + if (day_within_year <= 30) { return 0; } - else if (day_within_year < 59 + in_leap_year) - { - return 1; - } - else if (day_within_year < 90 + in_leap_year) - { - return 2; - } - else if (day_within_year < 120 + in_leap_year) - { - return 3; - } - else if (day_within_year < 151 + in_leap_year) - { - return 4; - } - else if (day_within_year < 181 + in_leap_year) - { - return 5; - } - else if (day_within_year < 212 + in_leap_year) - { - return 6; - } - else if (day_within_year < 243 + in_leap_year) - { - return 7; - } - else if (day_within_year < 273 + in_leap_year) - { - return 8; - } - else if (day_within_year < 304 + in_leap_year) - { - return 9; - } - else if (day_within_year < 334 + in_leap_year) + + day_within_year -= ecma_date_in_leap_year (year); + + JERRY_ASSERT (day_within_year < 365); + + for (int i = 0; i < 10; i++) { - return 10; + if (day_within_year <= ecma_date_month_end_day[i]) + { + return i + 1; + } } return 11; @@ -332,83 +223,43 @@ ecma_date_month_from_time (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.5 * - * Used by: - * - The Date.prototype.getDate routine. (Generated.) - * - The Date.prototype.getUTCDate routine. (Generated.) - * - The Date.prototype.setMonth routine. - * - The Date.prototype.setUTCMonth routine. - * - The Date.prototype.setFullYear routine. - * - The Date.prototype.setUTCFullYear routine. - * - * @return date number + * @return date number */ ecma_number_t ecma_date_date_from_time (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) + JERRY_ASSERT (!ecma_number_is_nan (time)); + + ecma_number_t year = ecma_date_year_from_time (time); + int day_within_year = (int) (ecma_date_day (time) - ecma_date_day_from_year (year)); + + JERRY_ASSERT (day_within_year >= 0); + + if (day_within_year <= 30) { - return time; /* time is NaN */ + return day_within_year + 1; } - ecma_number_t in_leap_year = ecma_date_in_leap_year (time); - ecma_number_t day_within_year = ecma_date_day_within_year (time); - JERRY_ASSERT (!ecma_number_is_nan (ecma_date_month_from_time (time))); - int month = ecma_number_to_int32 (ecma_date_month_from_time (time)); + int leap_year = ecma_date_in_leap_year (year); - switch (month) + if (day_within_year <= 58 + leap_year) { - case 0: - { - return day_within_year + 1; - } - case 1: - { - return day_within_year - 30 ; - } - case 2: - { - return day_within_year - 58 - in_leap_year; - } - case 3: - { - return day_within_year - 89 - in_leap_year; - } - case 4: - { - return day_within_year - 119 - in_leap_year; - } - case 5: - { - return day_within_year - 150 - in_leap_year; - } - case 6: - { - return day_within_year - 180 - in_leap_year; - } - case 7: - { - return day_within_year - 211 - in_leap_year; - } - case 8: - { - return day_within_year - 242 - in_leap_year; - } - case 9: - { - return day_within_year - 272 - in_leap_year; - } - case 10: - { - return day_within_year - 303 - in_leap_year; - } - case 11: + return day_within_year - 30; + } + + day_within_year -= leap_year; + + JERRY_ASSERT (day_within_year < 365); + + for (int i = 1; i < 10; i++) + { + if (day_within_year <= ecma_date_month_end_day[i]) { - return day_within_year - 333 - in_leap_year; + return day_within_year - ecma_date_month_end_day[i - 1]; } } - JERRY_UNREACHABLE (); - return 0; + return day_within_year - 333; } /* ecma_date_date_from_time */ /** @@ -423,16 +274,14 @@ ecma_date_date_from_time (ecma_number_t time) /**< time value */ * * @return weekday number */ -inline ecma_number_t __attr_always_inline___ +ecma_number_t ecma_date_week_day (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) - { - return time; /* time is NaN */ - } + JERRY_ASSERT (!ecma_number_is_nan (time)); ecma_number_t week_day = (ecma_number_t) fmod ((ecma_date_day (time) + 4), 7); - return (week_day < 0) ? 7 + week_day : week_day; + + return (week_day < 0) ? (7 + week_day) : week_day; } /* ecma_date_week_day */ /** @@ -441,19 +290,12 @@ ecma_date_week_day (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.7 * - * @return local time zone adjustment + * @return local time zone adjustment */ -inline ecma_number_t __attr_always_inline___ -ecma_date_local_tza () +static inline ecma_number_t __attr_always_inline___ +ecma_date_local_tza (jerry_time_zone_t *tz) /**< time zone information */ { - jerry_time_zone_t tz; - - if (!jerry_port_get_time_zone (&tz)) - { - return ecma_number_make_nan (); - } - - return tz.offset * -ECMA_DATE_MS_PER_MINUTE; + return tz->offset * -ECMA_DATE_MS_PER_MINUTE; } /* ecma_date_local_tza */ /** @@ -462,24 +304,15 @@ ecma_date_local_tza () * See also: * ECMA-262 v5, 15.9.1.8 * - * @return daylight saving time adjustment + * @return daylight saving time adjustment */ -inline ecma_number_t __attr_always_inline___ -ecma_date_daylight_saving_ta (ecma_number_t time) /**< time value */ +static inline ecma_number_t __attr_always_inline___ +ecma_date_daylight_saving_ta (jerry_time_zone_t *tz, /**< time zone information */ + ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) - { - return time; /* time is NaN */ - } - - jerry_time_zone_t tz; - - if (!jerry_port_get_time_zone (&tz)) - { - return ecma_number_make_nan (); - } + JERRY_ASSERT (!ecma_number_is_nan (time)); - return tz.daylight_saving_time * ECMA_DATE_MS_PER_HOUR; + return tz->daylight_saving_time * ECMA_DATE_MS_PER_HOUR; } /* ecma_date_daylight_saving_ta */ /** @@ -488,30 +321,21 @@ ecma_date_daylight_saving_ta (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.9 * - * Used by: - * - All Date.prototype.getUTC routines. (Generated.) - * - The Date.prototype.getTimezoneOffset routine. - * - The Date.prototype.setMilliseconds routine. - * - The Date.prototype.setSeconds routine. - * - The Date.prototype.setMinutes routine. - * - The Date.prototype.setHours routine. - * - The Date.prototype.setDate routine. - * - The Date.prototype.setMonth routine. - * - The Date.prototype.setFullYear routine. - * - The ecma_date_timezone_offset helper function. - * - * @return local time + * @return local time */ inline ecma_number_t __attr_always_inline___ -ecma_date_local_time (ecma_number_t time) /**< time value */ +ecma_date_local_time_zone (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) + jerry_time_zone_t tz; + + if (ecma_number_is_nan (time) + || !jerry_port_get_time_zone (&tz)) { - return time; /* time is NaN */ + return ecma_number_make_nan (); } - return time + ecma_date_local_tza () + ecma_date_daylight_saving_ta (time); -} /* ecma_date_local_time */ + return ecma_date_local_tza (&tz) + ecma_date_daylight_saving_ta (&tz, time); +} /* ecma_date_local_time_zone */ /** * Helper function to get utc from local time. @@ -519,22 +343,21 @@ ecma_date_local_time (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.9 * - * Used by: - * - The Date object's 'parse' routine. - * - The [[Construct]] of built-in Date object rutine. - * - * @return utc value + * @return utc time */ -inline ecma_number_t __attr_always_inline___ +ecma_number_t ecma_date_utc (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) + jerry_time_zone_t tz; + + if (ecma_number_is_nan (time) + || !jerry_port_get_time_zone (&tz)) { - return time; /* time is NaN */ + return ecma_number_make_nan (); } - ecma_number_t simple_utc_time = time - ecma_date_local_tza (); - return simple_utc_time - ecma_date_daylight_saving_ta (simple_utc_time); + ecma_number_t simple_utc_time = time - ecma_date_local_tza (&tz); + return simple_utc_time - ecma_date_daylight_saving_ta (&tz, simple_utc_time); } /* ecma_date_utc */ /** @@ -543,25 +366,12 @@ ecma_date_utc (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.10 * - * Used by: - * - The Date.prototype.getHour routine. (Generated.) - * - The Date.prototype.getUTCHour routine. (Generated.) - * - The Date.prototype.setMilliseconds routine. - * - The Date.prototype.setUTCMilliseconds routine. - * - The Date.prototype.setSeconds routine. - * - The Date.prototype.setUTCSeconds routine. - * - The Date.prototype.setMinutes routine. - * - The Date.prototype.setUTCMinutes routine. - * - * @return hour value + * @return hour value */ -inline ecma_number_t __attr_always_inline___ +ecma_number_t ecma_date_hour_from_time (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) - { - return time; /* time is NaN */ - } + JERRY_ASSERT (!ecma_number_is_nan (time)); ecma_number_t hour = (ecma_number_t) fmod (floor (time / ECMA_DATE_MS_PER_HOUR), ECMA_DATE_HOURS_PER_DAY); @@ -574,25 +384,12 @@ ecma_date_hour_from_time (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.10 * - * Used by: - * - The Date.prototype.getMinutes routine. (Generated.) - * - The Date.prototype.getUTCMinutes routine. (Generated.) - * - The Date.prototype.setMilliseconds routine. - * - The Date.prototype.setUTCMilliseconds routine. - * - The Date.prototype.setSeconds routine. - * - The Date.prototype.setUTCSeconds routine. - * - The Date.prototype.setHours routine. - * - The Date.prototype.setUTCHours routine. - * - * @return minute value + * @return minute value */ -inline ecma_number_t __attr_always_inline___ +ecma_number_t ecma_date_min_from_time (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) - { - return time; /* time is NaN */ - } + JERRY_ASSERT (!ecma_number_is_nan (time)); ecma_number_t min = (ecma_number_t) fmod (floor (time / ECMA_DATE_MS_PER_MINUTE), ECMA_DATE_MINUTES_PER_HOUR); @@ -605,25 +402,12 @@ ecma_date_min_from_time (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.10 * - * Used by: - * - The Date.prototype.getSeconds routine. (Generated.) - * - The Date.prototype.getUTCSeconds routine. (Generated.) - * - The Date.prototype.setMilliseconds routine. - * - The Date.prototype.setUTCMilliseconds routine. - * - The Date.prototype.setMinutes routine. - * - The Date.prototype.setUTCMinutes routine. - * - The Date.prototype.setHours routine. - * - The Date.prototype.setUTCHours routine. - * - * @return second value + * @return second value */ -inline ecma_number_t __attr_always_inline___ +ecma_number_t ecma_date_sec_from_time (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) - { - return time; /* time is NaN */ - } + JERRY_ASSERT (!ecma_number_is_nan (time)); ecma_number_t sec = (ecma_number_t) fmod (floor (time / ECMA_DATE_MS_PER_SECOND), ECMA_DATE_SECONDS_PER_MINUTE); @@ -636,25 +420,12 @@ ecma_date_sec_from_time (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.10 * - * Used by: - * - The Date.prototype.getMilliseconds routine. (Generated.) - * - The Date.prototype.getUTCMilliseconds routine. (Generated.) - * - The Date.prototype.setSeconds routine. - * - The Date.prototype.setUTCSeconds routine. - * - The Date.prototype.setMinutes routine. - * - The Date.prototype.setUTCMinutes routine. - * - The Date.prototype.setHours routine. - * - The Date.prototype.setUTCHours routine. - * - * @return millisecond value + * @return millisecond value */ -inline ecma_number_t __attr_always_inline___ +ecma_number_t ecma_date_ms_from_time (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) - { - return time; /* time is NaN */ - } + JERRY_ASSERT (!ecma_number_is_nan (time)); ecma_number_t milli = (ecma_number_t) fmod (time, ECMA_DATE_MS_PER_SECOND); return (milli < 0) ? ECMA_DATE_MS_PER_SECOND + milli : milli; @@ -666,17 +437,7 @@ ecma_date_ms_from_time (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.1.11 * - * Used by: - * - The Date.prototype.setMilliseconds routine. - * - The Date.prototype.setUTCMilliseconds routine. - * - The Date.prototype.setSeconds routine. - * - The Date.prototype.setUTCSeconds routine. - * - The Date.prototype.setMinutes routine. - * - The Date.prototype.setUTCMinutes routine. - * - The Date.prototype.setHours routine. - * - The Date.prototype.setUTCHours routine. - * - * @return time value + * @return time value */ ecma_number_t ecma_date_make_time (ecma_number_t hour, /**< hour value */ @@ -714,15 +475,7 @@ ecma_date_make_time (ecma_number_t hour, /**< hour value */ * See also: * ECMA-262 v5, 15.9.1.12 * - * Used by: - * - The Date.prototype.setDate routine. - * - The Date.prototype.setUTCDate routine. - * - The Date.prototype.setMonth routine. - * - The Date.prototype.setUTCMonth routine. - * - The Date.prototype.setFullYear routine. - * - The Date.prototype.setUTCFullYear routine. - * - * @return day value + * @return day value */ ecma_number_t ecma_date_make_day (ecma_number_t year, /**< year value */ @@ -755,7 +508,7 @@ ecma_date_make_day (ecma_number_t year, /**< year value */ /** * The algorithm below searches the following date: ym-mn-1 - * To find this time it starts from the beggining of the year (ym) + * To find this time it starts from the beginning of the year (ym) * then find the first day of the month. */ if (ecma_date_year_from_time (time) == ym) @@ -782,21 +535,26 @@ ecma_date_make_day (ecma_number_t year, /**< year value */ * See also: * ECMA-262 v5, 15.9.1.13 * - * @return date value + * @return date value */ -inline ecma_number_t __attr_always_inline___ +ecma_number_t ecma_date_make_date (ecma_number_t day, /**< day value */ ecma_number_t time) /**< time value */ { if (ecma_number_is_nan (day) - || ecma_number_is_nan (time) - || ecma_number_is_infinity (day) - || ecma_number_is_infinity (time)) + || ecma_number_is_nan (time)) { return ecma_number_make_nan (); } - return day * ECMA_DATE_MS_PER_DAY + time; + ecma_number_t result = day * ECMA_DATE_MS_PER_DAY + time; + + if (ecma_number_is_infinity (result)) + { + return ecma_number_make_nan (); + } + + return result; } /* ecma_date_make_date */ /** @@ -805,13 +563,9 @@ ecma_date_make_date (ecma_number_t day, /**< day value */ * See also: * ECMA-262 v5, 15.9.1.14 * - * Used by: - * - The Date.prototype.setTime routine. - * - The ecma_builtin_date_prototype_dispatch_set helper function. - * - * @return number of milliseconds + * @return number of milliseconds */ -inline ecma_number_t __attr_always_inline___ +ecma_number_t ecma_date_time_clip (ecma_number_t time) /**< time value */ { if (ecma_number_is_nan (time) @@ -830,138 +584,192 @@ ecma_date_time_clip (ecma_number_t time) /**< time value */ * See also: * ECMA-262 v5, 15.9.5.26 * - * Used by: - * - The Date.prototype.getTimezoneOffset routine. (Generated.) - * - * @return timezone offset + * @return timezone offset */ inline ecma_number_t __attr_always_inline___ ecma_date_timezone_offset (ecma_number_t time) /**< time value */ { - if (ecma_number_is_nan (time)) - { - return ecma_number_make_nan (); - } + JERRY_ASSERT (!ecma_number_is_nan (time)); - return (time - ecma_date_local_time (time)) / ECMA_DATE_MS_PER_MINUTE; + return (-ecma_date_local_time_zone (time)) / ECMA_DATE_MS_PER_MINUTE; } /* ecma_date_timezone_offset */ /** - * Common function to copy utf8 characters. + * Common function to convert date to string. * - * @return next destination buffer position - */ -static lit_utf8_byte_t * -ecma_date_value_copy_utf8_bytes (lit_utf8_byte_t *dest_p, /**< destination buffer */ - const char *source_p) /**< source buffer */ -{ - while (*source_p != LIT_CHAR_NULL) - { - *dest_p++ = (lit_utf8_byte_t) *source_p++; - } - return dest_p; -} /* ecma_date_value_copy_utf8_bytes */ - -/** - * Common function to generate fixed width, right aligned decimal numbers. - * - * @return next destination buffer position + * @return ecma value + * Returned value must be freed with ecma_free_value. */ -static lit_utf8_byte_t * -ecma_date_value_number_to_bytes (lit_utf8_byte_t *dest_p, /**< destination buffer */ - int32_t number, /**< number */ - int32_t width) /**< width */ +static ecma_value_t +ecma_date_to_string_format (ecma_number_t datetime_number, /**< datetime */ + const char *format_p) /**< format buffer */ { - dest_p += width; - lit_utf8_byte_t *result_p = dest_p; - - do + const char *day_names_p[8] = { - dest_p--; - *dest_p = (lit_utf8_byte_t) ((number % 10) + (int32_t) LIT_CHAR_0); - number /= 10; - } - while (--width > 0); - - return result_p; -} /* ecma_date_value_number_to_bytes */ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; -/** - * Common function to get the 3 character abbreviation of a week day. - * - * @return next destination buffer position - */ -static lit_utf8_byte_t * -ecma_date_value_week_day_to_abbreviation (lit_utf8_byte_t *dest_p, /**< destination buffer */ - ecma_number_t datetime_number) /**< datetime */ -{ - const char *abbreviations_p[8] = + const char *month_names_p[13] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "---" + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - int32_t day = (int32_t) ecma_date_week_day (datetime_number); + const uint32_t date_buffer_length = 34; + lit_utf8_byte_t date_buffer[date_buffer_length]; - if (day < 0 || day > 6) + lit_utf8_byte_t *dest_p = date_buffer; + + while (*format_p != LIT_CHAR_NULL) { - /* Just for safety, it should never happen. */ - day = 7; - } + if (*format_p != LIT_CHAR_DOLLAR_SIGN) + { + *dest_p++ = (lit_utf8_byte_t) *format_p++; + continue; + } - return ecma_date_value_copy_utf8_bytes (dest_p, abbreviations_p[day]); -} /* ecma_date_value_week_day_to_abbreviation */ + format_p++; -/** - * Common function to get the 3 character abbreviation of a month. - * - * @return next destination buffer position - */ -static lit_utf8_byte_t * -ecma_date_value_month_to_abbreviation (lit_utf8_byte_t *dest_p, /**< destination buffer */ - ecma_number_t datetime_number) /**< datetime */ -{ - const char *abbreviations_p[13] = - { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "---" - }; + const char *str_p = NULL; + int32_t number = 0; + int32_t number_length = 0; - int32_t month = (int32_t) ecma_date_month_from_time (datetime_number); + switch (*format_p) + { + case LIT_CHAR_UPPERCASE_Y: /* Year. */ + { + number = (int32_t) ecma_date_year_from_time (datetime_number); + number_length = 4; + break; + } + case LIT_CHAR_UPPERCASE_M: /* Month. */ + { + int32_t month = (int32_t) ecma_date_month_from_time (datetime_number); + + JERRY_ASSERT (month >= 0 && month <= 11); + + str_p = month_names_p[month]; + break; + } + case LIT_CHAR_UPPERCASE_O: /* Month as number. */ + { + /* The 'ecma_date_month_from_time' (ECMA 262 v5, 15.9.1.4) returns a + * number from 0 to 11, but we have to print the month from 1 to 12 + * for ISO 8601 standard (ECMA 262 v5, 15.9.1.15). */ + number = ((int32_t) ecma_date_month_from_time (datetime_number)) + 1; + number_length = 2; + break; + } + case LIT_CHAR_UPPERCASE_D: /* Day. */ + { + number = (int32_t) ecma_date_date_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_UPPERCASE_W: /* Day of week. */ + { + int32_t day = (int32_t) ecma_date_week_day (datetime_number); + + JERRY_ASSERT (day >= 0 && day <= 6); + + str_p = day_names_p[day]; + break; + } + case LIT_CHAR_LOWERCASE_H: /* Hour. */ + { + number = (int32_t) ecma_date_hour_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_LOWERCASE_M: /* Minutes. */ + { + number = (int32_t) ecma_date_min_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_LOWERCASE_S: /* Seconds. */ + { + number = (int32_t) ecma_date_sec_from_time (datetime_number); + number_length = 2; + break; + } + case LIT_CHAR_LOWERCASE_I: /* Milliseconds. */ + { + number = (int32_t) ecma_date_ms_from_time (datetime_number); + number_length = 3; + break; + } + case LIT_CHAR_LOWERCASE_Z: /* Time zone minutes part. */ + { + int32_t time_zone = (int32_t) ecma_date_local_time_zone (datetime_number); + + if (time_zone >= 0) + { + *dest_p++ = LIT_CHAR_PLUS; + } + else + { + *dest_p++ = LIT_CHAR_MINUS; + time_zone = -time_zone; + } + + number = time_zone / (int32_t) ECMA_DATE_MS_PER_HOUR; + number_length = 2; + break; + } + case LIT_CHAR_UPPERCASE_Z: /* Time zone seconds part. */ + { + int32_t time_zone = (int32_t) ecma_date_local_time_zone (datetime_number); + + if (time_zone < 0) + { + time_zone = -time_zone; + } + + number = time_zone % (int32_t) ECMA_DATE_MS_PER_HOUR; + number_length = 2; + break; + } + default: + { + JERRY_UNREACHABLE (); + break; + } + } - if (month < 0 || month > 11) - { - /* Just for safety, it should never happen. */ - month = 12; - } + format_p++; - return ecma_date_value_copy_utf8_bytes (dest_p, abbreviations_p[(int) month]); -} /* ecma_date_value_month_to_abbreviation */ + if (str_p != NULL) + { + /* Print string values. */ + do + { + *dest_p++ = (lit_utf8_byte_t) *str_p++; + } + while (*str_p != LIT_CHAR_NULL); + + continue; + } -/** - * The common 17 character long part of ecma_date_value_to_string and ecma_date_value_to_utc_string. - * - * @return next destination buffer position - */ -static lit_utf8_byte_t * -ecma_date_value_to_string_common (lit_utf8_byte_t *dest_p, /**< destination buffer */ - ecma_number_t datetime_number) /**< datetime */ -{ - ecma_number_t year = ecma_date_year_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) year, 4); - *dest_p++ = LIT_CHAR_SP; + /* Print right aligned number values. */ + JERRY_ASSERT (number_length > 0); - ecma_number_t hours = ecma_date_hour_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) hours, 2); - *dest_p++ = LIT_CHAR_COLON; + dest_p += number_length; + lit_utf8_byte_t *buffer_p = dest_p; - ecma_number_t minutes = ecma_date_min_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) minutes, 2); - *dest_p++ = LIT_CHAR_COLON; + do + { + buffer_p--; + *buffer_p = (lit_utf8_byte_t) ((number % 10) + (int32_t) LIT_CHAR_0); + number /= 10; + } + while (--number_length); + } - ecma_number_t seconds = ecma_date_sec_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) seconds, 2); + JERRY_ASSERT (dest_p <= date_buffer + date_buffer_length); - return ecma_date_value_copy_utf8_bytes (dest_p, " GMT"); -} /* ecma_date_value_to_string_common */ + return ecma_make_string_value (ecma_new_ecma_string_from_utf8 (date_buffer, + (lit_utf8_size_t) (dest_p - date_buffer))); +} /* ecma_date_to_string_format */ /** * Common function to create a time zone specific string from a numeric value. @@ -976,53 +784,8 @@ ecma_date_value_to_string_common (lit_utf8_byte_t *dest_p, /**< destination buff ecma_value_t ecma_date_value_to_string (ecma_number_t datetime_number) /**< datetime */ { - /* - * Character length of the result string. - */ - const uint32_t result_string_length = 34; - - lit_utf8_byte_t character_buffer[result_string_length]; - lit_utf8_byte_t *dest_p = character_buffer; - - datetime_number = ecma_date_local_time (datetime_number); - - dest_p = ecma_date_value_week_day_to_abbreviation (dest_p, datetime_number); - *dest_p++ = LIT_CHAR_SP; - - dest_p = ecma_date_value_month_to_abbreviation (dest_p, datetime_number); - *dest_p++ = LIT_CHAR_SP; - - ecma_number_t day = ecma_date_date_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) day, 2); - *dest_p++ = LIT_CHAR_SP; - - dest_p = ecma_date_value_to_string_common (dest_p, datetime_number); - - int32_t time_zone = (int32_t) (ecma_date_local_tza () + ecma_date_daylight_saving_ta (datetime_number)); - if (time_zone >= 0) - { - *dest_p++ = LIT_CHAR_PLUS; - } - else - { - *dest_p++ = LIT_CHAR_MINUS; - time_zone = -time_zone; - } - - dest_p = ecma_date_value_number_to_bytes (dest_p, - time_zone / (int32_t) ECMA_DATE_MS_PER_HOUR, - 2); - *dest_p++ = LIT_CHAR_COLON; - dest_p = ecma_date_value_number_to_bytes (dest_p, - time_zone % (int32_t) ECMA_DATE_MS_PER_HOUR, - 2); - - JERRY_ASSERT ((uint32_t) (dest_p - character_buffer) == result_string_length); - - ecma_string_t *date_string_p = ecma_new_ecma_string_from_utf8 (character_buffer, - result_string_length); - - return ecma_make_string_value (date_string_p); + datetime_number += ecma_date_local_time_zone (datetime_number); + return ecma_date_to_string_format (datetime_number, "$W $M $D $Y $h:$m:$s GMT$z:$Z"); } /* ecma_date_value_to_string */ /** @@ -1037,33 +800,7 @@ ecma_date_value_to_string (ecma_number_t datetime_number) /**< datetime */ ecma_value_t ecma_date_value_to_utc_string (ecma_number_t datetime_number) /**< datetime */ { - /* - * Character length of the result string. - */ - const uint32_t result_string_length = 29; - - lit_utf8_byte_t character_buffer[result_string_length]; - lit_utf8_byte_t *dest_p = character_buffer; - - dest_p = ecma_date_value_week_day_to_abbreviation (dest_p, datetime_number); - *dest_p++ = LIT_CHAR_COMMA; - *dest_p++ = LIT_CHAR_SP; - - ecma_number_t day = ecma_date_date_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) day, 2); - *dest_p++ = LIT_CHAR_SP; - - dest_p = ecma_date_value_month_to_abbreviation (dest_p, datetime_number); - *dest_p++ = LIT_CHAR_SP; - - dest_p = ecma_date_value_to_string_common (dest_p, datetime_number); - - JERRY_ASSERT ((uint32_t) (dest_p - character_buffer) == result_string_length); - - ecma_string_t *date_string_p = ecma_new_ecma_string_from_utf8 (character_buffer, - result_string_length); - - return ecma_make_string_value (date_string_p); + return ecma_date_to_string_format (datetime_number, "$W, $D $M $Y $h:$m:$s GMT"); } /* ecma_date_value_to_utc_string */ /** @@ -1078,53 +815,7 @@ ecma_date_value_to_utc_string (ecma_number_t datetime_number) /**< datetime */ ecma_value_t ecma_date_value_to_iso_string (ecma_number_t datetime_number) /**<datetime */ { - /* - * Character length of the result string. - */ - const uint32_t result_string_length = 24; - - lit_utf8_byte_t character_buffer[result_string_length]; - lit_utf8_byte_t *dest_p = character_buffer; - - ecma_number_t year = ecma_date_year_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) year, 4); - *dest_p++ = LIT_CHAR_MINUS; - - /* - * Note: - * 'ecma_date_month_from_time' (ECMA 262 v5, 15.9.1.4) returns a number from 0 to 11, - * but we have to print the month from 1 to 12 for ISO 8601 standard (ECMA 262 v5, 15.9.1.15). - */ - ecma_number_t month = ecma_date_month_from_time (datetime_number) + 1; - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) month, 2); - *dest_p++ = LIT_CHAR_MINUS; - - ecma_number_t day = ecma_date_date_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) day, 2); - *dest_p++ = LIT_CHAR_UPPERCASE_T; - - ecma_number_t hours = ecma_date_hour_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) hours, 2); - *dest_p++ = LIT_CHAR_COLON; - - ecma_number_t minutes = ecma_date_min_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) minutes, 2); - *dest_p++ = LIT_CHAR_COLON; - - ecma_number_t seconds = ecma_date_sec_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) seconds, 2); - *dest_p++ = LIT_CHAR_DOT; - - ecma_number_t milliseconds = ecma_date_ms_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) milliseconds, 3); - *dest_p++ = LIT_CHAR_UPPERCASE_Z; - - JERRY_ASSERT ((uint32_t) (dest_p - character_buffer) == result_string_length); - - ecma_string_t *date_string_p = ecma_new_ecma_string_from_utf8 (character_buffer, - result_string_length); - - return ecma_make_string_value (date_string_p); + return ecma_date_to_string_format (datetime_number, "$Y-$O-$DT$h:$m:$s.$iZ"); } /* ecma_date_value_to_iso_string */ /** @@ -1139,36 +830,7 @@ ecma_date_value_to_iso_string (ecma_number_t datetime_number) /**<datetime */ ecma_value_t ecma_date_value_to_date_string (ecma_number_t datetime_number) /**<datetime */ { - /* - * Character length of the result string. - */ - const uint32_t result_string_length = 10; - - lit_utf8_byte_t character_buffer[result_string_length]; - lit_utf8_byte_t *dest_p = character_buffer; - - ecma_number_t year = ecma_date_year_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) year, 4); - *dest_p++ = LIT_CHAR_MINUS; - - /* - * Note: - * 'ecma_date_month_from_time' (ECMA 262 v5, 15.9.1.4) returns a number from 0 to 11, - * but we have to print the month from 1 to 12 for ISO 8601 standard (ECMA 262 v5, 15.9.1.15). - */ - ecma_number_t month = ecma_date_month_from_time (datetime_number) + 1; - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) month, 2); - *dest_p++ = LIT_CHAR_MINUS; - - ecma_number_t day = ecma_date_date_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) day, 2); - - JERRY_ASSERT ((uint32_t) (dest_p - character_buffer) == result_string_length); - - ecma_string_t *date_string_p = ecma_new_ecma_string_from_utf8 (character_buffer, - result_string_length); - - return ecma_make_string_value (date_string_p); + return ecma_date_to_string_format (datetime_number, "$Y-$O-$D"); } /* ecma_date_value_to_date_string */ /** @@ -1183,35 +845,7 @@ ecma_date_value_to_date_string (ecma_number_t datetime_number) /**<datetime */ ecma_value_t ecma_date_value_to_time_string (ecma_number_t datetime_number) /**<datetime */ { - /* - * Character length of the result string. - */ - const uint32_t result_string_length = 12; - - lit_utf8_byte_t character_buffer[result_string_length]; - lit_utf8_byte_t *dest_p = character_buffer; - - ecma_number_t hours = ecma_date_hour_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) hours, 2); - *dest_p++ = LIT_CHAR_COLON; - - ecma_number_t minutes = ecma_date_min_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) minutes, 2); - *dest_p++ = LIT_CHAR_COLON; - - ecma_number_t seconds = ecma_date_sec_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) seconds, 2); - *dest_p++ = LIT_CHAR_DOT; - - ecma_number_t milliseconds = ecma_date_ms_from_time (datetime_number); - dest_p = ecma_date_value_number_to_bytes (dest_p, (int32_t) milliseconds, 3); - - JERRY_ASSERT ((uint32_t) (dest_p - character_buffer) == result_string_length); - - ecma_string_t *time_string_p = ecma_new_ecma_string_from_utf8 (character_buffer, - result_string_length); - - return ecma_make_string_value (time_string_p); + return ecma_date_to_string_format (datetime_number, "$h:$m:$s.$i"); } /* ecma_date_value_to_time_string */ /** |