diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp index 48080f0c1..e42bd2334 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp @@ -70,7 +70,7 @@ ecma_builtin_date_prototype_to_string (ecma_value_t this_arg) /**< this argument } else { - ret_value = ecma_date_value_to_string (*prim_num_p, ECMA_DATE_LOCAL); + ret_value = ecma_date_value_to_string (*prim_num_p); } ECMA_FINALIZE (prim_value); @@ -1136,7 +1136,7 @@ ecma_builtin_date_prototype_to_utc_string (ecma_value_t this_arg) /**< this argu } else { - ret_value = ecma_date_value_to_string (*prim_num_p, ECMA_DATE_UTC); + ret_value = ecma_date_value_to_utc_string (*prim_num_p); } ECMA_FINALIZE (prim_value); @@ -1170,7 +1170,7 @@ ecma_builtin_date_prototype_to_iso_string (ecma_value_t this_arg) /**< this argu } else { - ret_value = ecma_date_value_to_string (*prim_num_p, ECMA_DATE_UTC); + ret_value = ecma_date_value_to_iso_string (*prim_num_p); } ECMA_FINALIZE (prim_value); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-date.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-date.cpp index 12074b666..4ad6b6396 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-date.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-date.cpp @@ -476,7 +476,7 @@ ecma_builtin_date_dispatch_call (const ecma_value_t *arguments_list_p __attr_unu ecma_builtin_date_now (ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED)), ret_value); - ret_value = ecma_date_value_to_string (*ecma_get_number_from_value (now_val), ECMA_DATE_LOCAL); + ret_value = ecma_date_value_to_string (*ecma_get_number_from_value (now_val)); ECMA_FINALIZE (now_val); 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 38c47b3a1..292fd1071 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.cpp @@ -22,6 +22,7 @@ #include "ecma-objects.h" #include "ecma-try-catch-macro.h" #include "fdlibm-math.h" +#include "lit-char-helpers.h" #ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN @@ -912,38 +913,230 @@ ecma_date_insert_num_with_sep (ecma_string_t **str_p, /**< input/output string * ecma_date_insert_leading_zeros (str_p, num, length); } /* ecma_date_insert_num_with_sep */ +/** + * Common function to copy utf8 characters. + * + * @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 + */ +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 */ +{ + dest_p += width; + lit_utf8_byte_t *result_p = dest_p; + + do + { + 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 */ + +/** + * 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] = + { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "---" + }; + + int32_t day = (int32_t) ecma_date_week_day (datetime_number); + + if (day < 0 || day > 6) + { + /* Just for safety, it should never happen. */ + day = 7; + } + + return ecma_date_value_copy_utf8_bytes (dest_p, abbreviations_p[day]); +} /* ecma_date_value_week_day_to_abbreviation */ + +/** + * 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", "---" + }; + + int32_t month = (int32_t) ecma_date_month_from_time (datetime_number); + + if (month < 0 || month > 11) + { + /* Just for safety, it should never happen. */ + month = 12; + } + + return ecma_date_value_copy_utf8_bytes (dest_p, abbreviations_p[(int) month]); +} /* ecma_date_value_month_to_abbreviation */ + +/** + * 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; + + 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); + + return ecma_date_value_copy_utf8_bytes (dest_p, " GMT"); +} /* ecma_date_value_to_string_common */ + +/** + * Length of string created by ecma_date_value_to_string + */ +#define ECMA_DATE_VALUE_TO_STRING_LENGTH 33 + /** * Common function to create a time zone specific string from a numeric value. * * Used by: * - The Date routine. * - The Date.prototype.toString routine. - * - The Date.prototype.toISOString routine. + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value. + */ +ecma_completion_value_t +ecma_date_value_to_string (ecma_number_t datetime_number) /**< datetime */ +{ + lit_utf8_byte_t character_buffer[ECMA_DATE_VALUE_TO_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)); + *dest_p++ = (time_zone >= 0) ? LIT_CHAR_PLUS : LIT_CHAR_MINUS; + + dest_p = ecma_date_value_number_to_bytes (dest_p, time_zone / 60, 2); + dest_p = ecma_date_value_number_to_bytes (dest_p, time_zone % 60, 2); + + JERRY_ASSERT (dest_p - character_buffer == ECMA_DATE_VALUE_TO_STRING_LENGTH); + + ecma_string_t *date_string_p = ecma_new_ecma_string_from_utf8 (character_buffer, + ECMA_DATE_VALUE_TO_STRING_LENGTH); + + return ecma_make_normal_completion_value (ecma_make_string_value (date_string_p)); +} /* ecma_date_value_to_string */ + +/** + * Length of string created by ecma_date_value_to_utc_string + */ +#define ECMA_DATE_VALUE_TO_UTC_STRING_LENGTH 29 + +/** + * Common function to create a time zone specific string from a numeric value. + * + * Used by: * - The Date.prototype.toUTCString routine. * * @return completion value * Returned value must be freed with ecma_free_completion_value. */ ecma_completion_value_t -ecma_date_value_to_string (ecma_number_t datetime_num, /**