mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Date toString methods follow the date format used by other JS engines:
new Date(0).toString () == "Thu Jan 01 1970 00:00:00 GMT+0000" new Date(0).toUTCString () == "Thu, 01 Jan 1970 00:00:00 GMT" new Date(0).toISOString () == "1970-01-01T00:00:00.000Z" Fixes S15.5.4.7_A1_T11.js test case. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg@inf.u-szeged.hu
This commit is contained in:
parent
4ee30cba5d
commit
5be41b44bb
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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, /**<datetime */
|
||||
ecma_date_timezone_t timezone) /**< timezone */
|
||||
ecma_date_value_to_utc_string (ecma_number_t datetime_number) /**< datetime */
|
||||
{
|
||||
lit_utf8_byte_t character_buffer[ECMA_DATE_VALUE_TO_UTC_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 (dest_p - character_buffer == ECMA_DATE_VALUE_TO_UTC_STRING_LENGTH);
|
||||
|
||||
ecma_string_t *date_string_p = ecma_new_ecma_string_from_utf8 (character_buffer,
|
||||
ECMA_DATE_VALUE_TO_UTC_STRING_LENGTH);
|
||||
|
||||
return ecma_make_normal_completion_value (ecma_make_string_value (date_string_p));
|
||||
} /* ecma_date_value_to_utc_string */
|
||||
|
||||
/**
|
||||
* Common function to create a time zone specific string from a numeric value.
|
||||
*
|
||||
* Used by:
|
||||
* - 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_iso_string (ecma_number_t datetime_num) /**<datetime */
|
||||
{
|
||||
ecma_string_t *output_str_p;
|
||||
ecma_number_t milliseconds;
|
||||
|
||||
if (timezone == ECMA_DATE_LOCAL)
|
||||
{
|
||||
datetime_num = ecma_date_local_time (datetime_num);
|
||||
milliseconds = ecma_date_ms_from_time (datetime_num);
|
||||
output_str_p = ecma_new_ecma_string_from_number (milliseconds);
|
||||
ecma_date_insert_leading_zeros (&output_str_p, milliseconds, 3);
|
||||
}
|
||||
else /* ECMA_DATE_UTC */
|
||||
{
|
||||
milliseconds = ecma_date_ms_from_time (datetime_num);
|
||||
output_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
|
||||
ecma_date_insert_num_with_sep (&output_str_p, milliseconds, LIT_MAGIC_STRING_Z_CHAR, 3);
|
||||
}
|
||||
ecma_number_t milliseconds = ecma_date_ms_from_time (datetime_num);
|
||||
output_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
|
||||
ecma_date_insert_num_with_sep (&output_str_p, milliseconds, LIT_MAGIC_STRING_Z_CHAR, 3);
|
||||
|
||||
ecma_number_t seconds = ecma_date_sec_from_time (datetime_num);
|
||||
ecma_date_insert_num_with_sep (&output_str_p, seconds, LIT_MAGIC_STRING_DOT_CHAR, 2);
|
||||
@ -969,7 +1162,7 @@ ecma_date_value_to_string (ecma_number_t datetime_num, /**<datetime */
|
||||
ecma_date_insert_num_with_sep (&output_str_p, year, LIT_MAGIC_STRING_MINUS_CHAR, 4);
|
||||
|
||||
return ecma_make_normal_completion_value (ecma_make_string_value (output_str_p));
|
||||
} /* ecma_date_value_to_string */
|
||||
} /* ecma_date_value_to_iso_string */
|
||||
|
||||
/**
|
||||
* Common function to get the primitive value of the Date object.
|
||||
|
||||
@ -125,7 +125,9 @@ extern void ecma_date_insert_num_with_sep (ecma_string_t **str_p,
|
||||
lit_magic_string_id_t magic_str_id,
|
||||
uint32_t length);
|
||||
|
||||
extern ecma_completion_value_t ecma_date_value_to_string (ecma_number_t datetime_num, ecma_date_timezone_t timezone);
|
||||
extern ecma_completion_value_t ecma_date_value_to_string (ecma_number_t datetime_num);
|
||||
extern ecma_completion_value_t ecma_date_value_to_utc_string (ecma_number_t datetime_num);
|
||||
extern ecma_completion_value_t ecma_date_value_to_iso_string (ecma_number_t datetime_num);
|
||||
extern ecma_completion_value_t ecma_date_get_primitive_value (ecma_value_t this_arg);
|
||||
|
||||
#endif /* !CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN */
|
||||
|
||||
@ -74,5 +74,6 @@ catch (e)
|
||||
assert (typeof Date (2015) == "string");
|
||||
assert (typeof Date() != typeof (new Date ()));
|
||||
assert (Date (Number.NaN) == Date ());
|
||||
|
||||
// Fixme: remove this case when Date() gives the current time.
|
||||
assert (Date (2015,1,2) == "1970-01-01T00:00:00.000");
|
||||
assert (Date (2015,1,2) == "Thu Jan 01 1970 00:00:00 GMT+0000");
|
||||
|
||||
@ -20,8 +20,8 @@ assert (new Date (2015, 7, 1, 0, Infinity, 0) == "Invalid Date");
|
||||
assert (new Date (NaN, 1, 1, 0, 0, 0) == "Invalid Date");
|
||||
assert (new Date (2015, NaN, 1, 0, 0, 0) == "Invalid Date");
|
||||
assert (new Date (2015, 7, 1, 0, NaN, 0) == "Invalid Date");
|
||||
assert (new Date ("2015-02-13") == "2015-02-13T00:00:00.000");
|
||||
assert (new Date ("2015-07-08T11:29:05.023") == "2015-07-08T11:29:05.023");
|
||||
assert (new Date ("2015-02-13") == "Fri Feb 13 2015 00:00:00 GMT+0000");
|
||||
assert (new Date ("2015-07-08T11:29:05.023") == "Wed Jul 08 2015 11:29:05 GMT+0000");
|
||||
|
||||
try
|
||||
{
|
||||
@ -34,6 +34,16 @@ catch (e)
|
||||
assert (e.message === "Incompatible type");
|
||||
}
|
||||
|
||||
var date = new Date(0);
|
||||
assert (date.toString() === "Thu Jan 01 1970 00:00:00 GMT+0000");
|
||||
assert (date.toUTCString() === "Thu, 01 Jan 1970 00:00:00 GMT");
|
||||
assert (date.toISOString() === "1970-01-01T00:00:00.000Z");
|
||||
|
||||
date = new Date("2015-08-12T09:40:20.000Z")
|
||||
assert (date.toString() === "Wed Aug 12 2015 09:40:20 GMT+0000");
|
||||
assert (date.toUTCString() === "Wed, 12 Aug 2015 09:40:20 GMT");
|
||||
assert (date.toISOString() === "2015-08-12T09:40:20.000Z");
|
||||
|
||||
assert (new Date (NaN).toDateString () == "Invalid Date");
|
||||
assert (new Date ("2015-02-13").toDateString () == "2015-02-13");
|
||||
assert (new Date ("2015-07-08T11:29:05.023").toDateString () == "2015-07-08");
|
||||
@ -100,8 +110,8 @@ catch (e)
|
||||
}
|
||||
|
||||
assert (new Date (NaN).toUTCString () == "Invalid Date");
|
||||
assert (new Date ("2015-07-16").toUTCString () == "2015-07-16T00:00:00.000Z");
|
||||
assert (new Date ("2015-07-16T11:29:05.023").toUTCString () == "2015-07-16T11:29:05.023Z");
|
||||
assert (new Date ("2015-07-16").toUTCString () == "Thu, 16 Jul 2015 00:00:00 GMT");
|
||||
assert (new Date ("2015-07-16T11:29:05.023").toUTCString () == "Thu, 16 Jul 2015 11:29:05 GMT");
|
||||
|
||||
try
|
||||
{
|
||||
@ -129,7 +139,7 @@ catch (e)
|
||||
}
|
||||
|
||||
date_time = new Date ("2015-07-08T11:29:05.023").toJSON ();
|
||||
assert (new Date (date_time) == "2015-07-08T11:29:05.023");
|
||||
assert (new Date (date_time).toISOString () == "2015-07-08T11:29:05.023Z");
|
||||
|
||||
assert (typeof Date (2015) == "string");
|
||||
assert (typeof Date() != typeof (new Date ()));
|
||||
@ -138,7 +148,7 @@ assert (Date (2015, 1, 1) == (new Date ()).toString ());
|
||||
assert (Date (Number.NaN) == Date ());
|
||||
|
||||
// Fixme: remove these cases when TZA and DST are supported.
|
||||
assert (new Date ("2015-07-08T11:29:05.023-02:00").toString() == "2015-07-08T13:29:05.023");
|
||||
assert (new Date ("2015-07-08T11:29:05.023-02:00").toLocaleString() == "2015-07-08T13:29:05.023");
|
||||
assert (new Date ("2015-07-08T11:29:05.023-02:00").toString () == "Wed Jul 08 2015 13:29:05 GMT+0000");
|
||||
assert (new Date ("2015-07-08T11:29:05.023-02:00").toLocaleString () == "Wed Jul 08 2015 13:29:05 GMT+0000");
|
||||
|
||||
assert (new Date ("2015-07-08T11:29:05.023Z").toISOString() == "2015-07-08T11:29:05.023Z");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user