aboutsummaryrefslogtreecommitdiff
path: root/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c
diff options
context:
space:
mode:
authorZoltan Herczeg <zherczeg.u-szeged@partner.samsung.com>2017-01-11 08:27:29 +0100
committerGitHub <noreply@github.com>2017-01-11 08:27:29 +0100
commit7d83293762aa36b14f1b697d05ab4aa462a83f31 (patch)
tree77aa9476700517f8ce61db1314d8a206e2705e9b /jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c
parent00b220bde675c363659a9d3c22f5d37e4409807e (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.c968
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 */
/**