Skip to content

Commit 577fc6d

Browse files
author
Roland Takacs
committed
Implement Date.prototype.toISOString()
JerryScript-DCO-1.0-Signed-off-by: Roland Takacs rtakacs.u-szeged@partner.samsung.com
1 parent b414329 commit 577fc6d

File tree

3 files changed

+82
-63
lines changed

3 files changed

+82
-63
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.cpp

Lines changed: 64 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
* @{
4343
*/
4444

45+
static ecma_completion_value_t
46+
ecma_builtin_date_prototype_to_iso_string (ecma_value_t this_arg);
47+
4548
/**
4649
* Insert leading zeros to a string of a number if needed.
4750
*/
@@ -103,66 +106,7 @@ ecma_date_insert_num_with_sep (ecma_string_t **str_p, /**< input/output string *
103106
static ecma_completion_value_t
104107
ecma_builtin_date_prototype_to_string (ecma_value_t this_arg) /**< this argument */
105108
{
106-
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
107-
108-
if (!ecma_is_value_object (this_arg)
109-
|| ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_DATE_UL)
110-
{
111-
ret_value = ecma_raise_type_error ("Incompatible type");
112-
}
113-
else
114-
{
115-
ECMA_TRY_CATCH (obj_this,
116-
ecma_op_to_object (this_arg),
117-
ret_value);
118-
119-
ecma_object_t *obj_p = ecma_get_object_from_value (obj_this);
120-
ecma_property_t *prim_value_prop_p;
121-
prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE);
122-
ecma_number_t *prim_value_num_p = ECMA_GET_NON_NULL_POINTER (ecma_number_t,
123-
prim_value_prop_p->u.internal_property.value);
124-
125-
if (ecma_number_is_nan (*prim_value_num_p))
126-
{
127-
ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INVALID_DATE_UL);
128-
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (magic_str_p));
129-
}
130-
else
131-
{
132-
ecma_number_t milliseconds = ecma_date_ms_from_time (*prim_value_num_p);
133-
ecma_string_t *output_str_p = ecma_new_ecma_string_from_number (milliseconds);
134-
ecma_date_insert_leading_zeros (&output_str_p, milliseconds, 3);
135-
136-
ecma_number_t seconds = ecma_date_sec_from_time (*prim_value_num_p);
137-
ecma_date_insert_num_with_sep (&output_str_p, seconds, LIT_MAGIC_STRING_DOT_CHAR, 2);
138-
139-
ecma_number_t minutes = ecma_date_min_from_time (*prim_value_num_p);
140-
ecma_date_insert_num_with_sep (&output_str_p, minutes, LIT_MAGIC_STRING_COLON_CHAR, 2);
141-
142-
ecma_number_t hours = ecma_date_hour_from_time (*prim_value_num_p);
143-
ecma_date_insert_num_with_sep (&output_str_p, hours, LIT_MAGIC_STRING_COLON_CHAR, 2);
144-
145-
ecma_number_t day = ecma_date_date_from_time (*prim_value_num_p);
146-
ecma_date_insert_num_with_sep (&output_str_p, day, LIT_MAGIC_STRING_TIME_SEP_U, 2);
147-
148-
/*
149-
* Note:
150-
* 'ecma_date_month_from_time' (ECMA 262 v5, 15.9.1.4) returns a number from 0 to 11,
151-
* but we have to print the month from 1 to 12 for ISO 8601 standard (ECMA 262 v5, 15.9.1.15).
152-
*/
153-
ecma_number_t month = ecma_date_month_from_time (*prim_value_num_p) + 1;
154-
ecma_date_insert_num_with_sep (&output_str_p, month, LIT_MAGIC_STRING_MINUS_CHAR, 2);
155-
156-
ecma_number_t year = ecma_date_year_from_time (*prim_value_num_p);
157-
ecma_date_insert_num_with_sep (&output_str_p, year, LIT_MAGIC_STRING_MINUS_CHAR, 4);
158-
159-
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (output_str_p));
160-
}
161-
162-
ECMA_FINALIZE (obj_this);
163-
}
164-
165-
return ret_value;
109+
return ecma_builtin_date_prototype_to_iso_string (this_arg);
166110
} /* ecma_builtin_date_prototype_to_string */
167111

168112
/**
@@ -1207,7 +1151,66 @@ ecma_builtin_date_prototype_to_utc_string (ecma_value_t this_arg) /**< this argu
12071151
static ecma_completion_value_t
12081152
ecma_builtin_date_prototype_to_iso_string (ecma_value_t this_arg) /**< this argument */
12091153
{
1210-
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg);
1154+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
1155+
1156+
if (!ecma_is_value_object (this_arg)
1157+
|| ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_DATE_UL)
1158+
{
1159+
ret_value = ecma_raise_type_error ("Incompatible type");
1160+
}
1161+
else
1162+
{
1163+
ECMA_TRY_CATCH (obj_this,
1164+
ecma_op_to_object (this_arg),
1165+
ret_value);
1166+
1167+
ecma_object_t *obj_p = ecma_get_object_from_value (obj_this);
1168+
ecma_property_t *prim_value_prop_p;
1169+
prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE);
1170+
ecma_number_t *prim_value_num_p = ECMA_GET_NON_NULL_POINTER (ecma_number_t,
1171+
prim_value_prop_p->u.internal_property.value);
1172+
1173+
if (ecma_number_is_nan (*prim_value_num_p))
1174+
{
1175+
ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INVALID_DATE_UL);
1176+
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (magic_str_p));
1177+
}
1178+
else
1179+
{
1180+
ecma_number_t milliseconds = ecma_date_ms_from_time (*prim_value_num_p);
1181+
ecma_string_t *output_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
1182+
ecma_date_insert_num_with_sep (&output_str_p, milliseconds, LIT_MAGIC_STRING_UTC_TIME_ZONE_U, 3);
1183+
1184+
ecma_number_t seconds = ecma_date_sec_from_time (*prim_value_num_p);
1185+
ecma_date_insert_num_with_sep (&output_str_p, seconds, LIT_MAGIC_STRING_DOT_CHAR, 2);
1186+
1187+
ecma_number_t minutes = ecma_date_min_from_time (*prim_value_num_p);
1188+
ecma_date_insert_num_with_sep (&output_str_p, minutes, LIT_MAGIC_STRING_COLON_CHAR, 2);
1189+
1190+
ecma_number_t hours = ecma_date_hour_from_time (*prim_value_num_p);
1191+
ecma_date_insert_num_with_sep (&output_str_p, hours, LIT_MAGIC_STRING_COLON_CHAR, 2);
1192+
1193+
ecma_number_t day = ecma_date_date_from_time (*prim_value_num_p);
1194+
ecma_date_insert_num_with_sep (&output_str_p, day, LIT_MAGIC_STRING_TIME_SEP_U, 2);
1195+
1196+
/*
1197+
* Note:
1198+
* 'ecma_date_month_from_time' (ECMA 262 v5, 15.9.1.4) returns a number from 0 to 11,
1199+
* but we have to print the month from 1 to 12 for ISO 8601 standard (ECMA 262 v5, 15.9.1.15).
1200+
*/
1201+
ecma_number_t month = ecma_date_month_from_time (*prim_value_num_p) + 1;
1202+
ecma_date_insert_num_with_sep (&output_str_p, month, LIT_MAGIC_STRING_MINUS_CHAR, 2);
1203+
1204+
ecma_number_t year = ecma_date_year_from_time (*prim_value_num_p);
1205+
ecma_date_insert_num_with_sep (&output_str_p, year, LIT_MAGIC_STRING_MINUS_CHAR, 4);
1206+
1207+
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (output_str_p));
1208+
}
1209+
1210+
ECMA_FINALIZE (obj_this);
1211+
}
1212+
1213+
return ret_value;
12111214
} /* ecma_builtin_date_prototype_to_iso_string */
12121215

12131216
/**

jerry-core/lit/lit-magic-strings.inc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_G_CHAR, "g")
219219
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_I_CHAR, "i")
220220
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_M_CHAR, "m")
221221
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TIME_SEP_U, "T")
222+
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UTC_TIME_ZONE_U, "Z")
222223
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SLASH_CHAR, "/")
223224
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BACKSLASH_CHAR, "\\")
224225
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP, "(?:)")

tests/jerry/date-tostring.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
// limitations under the License.
1515

1616
assert (new Date (NaN) == "Invalid Date");
17-
assert (new Date ("2015-02-13") == "2015-02-13T00:00:00.000");
18-
assert (new Date ("2015-07-08T11:29:05.023") == "2015-07-08T11:29:05.023");
17+
assert (new Date ("2015-02-13") == "2015-02-13T00:00:00.000Z");
18+
assert (new Date ("2015-07-08T11:29:05.023") == "2015-07-08T11:29:05.023Z");
1919

2020
try
2121
{
@@ -57,3 +57,18 @@ catch (e)
5757
assert (e instanceof TypeError);
5858
assert (e.message === "Incompatible type");
5959
}
60+
61+
assert (new Date (NaN).toISOString () == "Invalid Date");
62+
assert (new Date ("2015-07-16").toISOString () == "2015-07-16T00:00:00.000Z");
63+
assert (new Date ("2015-07-16T11:29:05.023").toISOString () == "2015-07-16T11:29:05.023Z");
64+
65+
try
66+
{
67+
Date.prototype.toISOString.call(-1);
68+
assert (false);
69+
}
70+
catch (e)
71+
{
72+
assert (e instanceof TypeError);
73+
assert (e.message === "Incompatible type");
74+
}

0 commit comments

Comments
 (0)