Skip to content

Commit 7d57c2c

Browse files
committed
Implement Date.prototype.toString
JerryScript-DCO-1.0-Signed-off-by: László Langó [email protected]
1 parent 146ac15 commit 7d57c2c

File tree

3 files changed

+133
-1
lines changed

3 files changed

+133
-1
lines changed

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

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@
1515
*/
1616

1717
#include "ecma-alloc.h"
18+
#include "ecma-builtin-helpers.h"
19+
#include "ecma-exceptions.h"
1820
#include "ecma-globals.h"
1921
#include "ecma-helpers.h"
22+
#include "ecma-objects.h"
23+
#include "ecma-try-catch-macro.h"
2024

2125
#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_DATE_BUILTIN
2226

@@ -37,6 +41,55 @@
3741
* @{
3842
*/
3943

44+
/**
45+
* Insert leading zeros to a string of a number if needed.
46+
*/
47+
static void
48+
ecma_date_insert_leading_zeros (ecma_string_t **str_p, /**< input/output string */
49+
ecma_number_t num, /**< input number */
50+
int32_t div) /**< "length" {10, 100, 1000} */
51+
{
52+
JERRY_ASSERT (div == 10 || div == 100 || div == 1000);
53+
54+
while (num < div && div > 1)
55+
{
56+
div /= 10;
57+
58+
ecma_string_t *zero_str_p = ecma_new_ecma_string_from_number (ECMA_NUMBER_ZERO);
59+
ecma_string_t *concat_p = ecma_concat_ecma_strings (zero_str_p, *str_p);
60+
ecma_deref_ecma_string (zero_str_p);
61+
ecma_deref_ecma_string (*str_p);
62+
*str_p = concat_p;
63+
}
64+
65+
} /* ecma_date_insert_leading_zeros */
66+
67+
/**
68+
* Insert a number to the start of a string with a specific separator character and
69+
* fix length.
70+
*/
71+
static void
72+
ecma_date_insert_num_with_sep (ecma_string_t **str_p, /**< input/output string */
73+
ecma_number_t num, /**< input number */
74+
lit_magic_string_id_t magic_str_id, /**< separator character id */
75+
int32_t div) /**< "length" {10, 100, 1000} */
76+
{
77+
ecma_string_t *magic_string_p = ecma_get_magic_string (magic_str_id);
78+
79+
ecma_string_t *concat_p = ecma_concat_ecma_strings (magic_string_p, *str_p);
80+
ecma_deref_ecma_string (magic_string_p);
81+
ecma_deref_ecma_string (*str_p);
82+
*str_p = concat_p;
83+
84+
ecma_string_t *num_str_p = ecma_new_ecma_string_from_number (num);
85+
concat_p = ecma_concat_ecma_strings (num_str_p, *str_p);
86+
ecma_deref_ecma_string (num_str_p);
87+
ecma_deref_ecma_string (*str_p);
88+
*str_p = concat_p;
89+
90+
ecma_date_insert_leading_zeros (str_p, num, div);
91+
} /* ecma_date_insert_num_with_sep */
92+
4093
/**
4194
* The Date.prototype object's 'toString' routine
4295
*
@@ -49,7 +102,65 @@
49102
static ecma_completion_value_t
50103
ecma_builtin_date_prototype_to_string (ecma_value_t this_arg) /**< this argument */
51104
{
52-
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg);
105+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
106+
107+
if (ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_DATE_UL)
108+
{
109+
ret_value = ecma_raise_type_error ("Incomplete Date type");
110+
}
111+
else
112+
{
113+
ECMA_TRY_CATCH (obj_this,
114+
ecma_op_to_object (this_arg),
115+
ret_value);
116+
117+
ecma_object_t *obj_p = ecma_get_object_from_value (obj_this);
118+
ecma_property_t *prim_value_prop_p;
119+
prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE);
120+
ecma_number_t *prim_value_num_p = ECMA_GET_NON_NULL_POINTER (ecma_number_t,
121+
prim_value_prop_p->u.internal_property.value);
122+
123+
if (ecma_number_is_nan (*prim_value_num_p))
124+
{
125+
ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INVALID_DATE_UL);
126+
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (magic_str_p));
127+
}
128+
else
129+
{
130+
ecma_number_t milliseconds = ecma_date_ms_from_time (*prim_value_num_p);
131+
ecma_string_t *output_str_p = ecma_new_ecma_string_from_number (milliseconds);
132+
ecma_date_insert_leading_zeros (&output_str_p, milliseconds, 100);
133+
134+
ecma_number_t seconds = ecma_date_sec_from_time (*prim_value_num_p);
135+
ecma_date_insert_num_with_sep (&output_str_p, seconds, LIT_MAGIC_STRING_DOT_CHAR, 10);
136+
137+
ecma_number_t minutes = ecma_date_min_from_time (*prim_value_num_p);
138+
ecma_date_insert_num_with_sep (&output_str_p, minutes, LIT_MAGIC_STRING_COLON_CHAR, 10);
139+
140+
ecma_number_t hours = ecma_date_hour_from_time (*prim_value_num_p);
141+
ecma_date_insert_num_with_sep (&output_str_p, hours, LIT_MAGIC_STRING_COLON_CHAR, 10);
142+
143+
ecma_number_t day = ecma_date_date_from_time (*prim_value_num_p);
144+
ecma_date_insert_num_with_sep (&output_str_p, day, LIT_MAGIC_STRING_TIME_SEP_U, 10);
145+
146+
/*
147+
* Note:
148+
* 'ecma_date_month_from_time' (ECMA 262 v5, 15.9.1.4) returns a number from 0 to 11,
149+
* but we have to print the month from 1 to 12 for ISO 8601 standard (ECMA 262 v5, 15.9.1.15).
150+
*/
151+
ecma_number_t month = ecma_date_month_from_time (*prim_value_num_p) + 1;
152+
ecma_date_insert_num_with_sep (&output_str_p, month, LIT_MAGIC_STRING_MINUS_CHAR, 10);
153+
154+
ecma_number_t year = ecma_date_year_from_time (*prim_value_num_p);
155+
ecma_date_insert_num_with_sep (&output_str_p, year, LIT_MAGIC_STRING_MINUS_CHAR, 1000);
156+
157+
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (output_str_p));
158+
}
159+
160+
ECMA_FINALIZE (obj_this);
161+
}
162+
163+
return ret_value;
53164
} /* ecma_builtin_date_prototype_to_string */
54165

55166
/**

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MIN_VALUE_U, "MIN_VALUE")
207207
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_POSITIVE_INFINITY_U, "POSITIVE_INFINITY")
208208
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NEGATIVE_INFINITY_U, "NEGATIVE_INFINITY")
209209
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMPACT_PROFILE_ERROR_UL, "CompactProfileError")
210+
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INVALID_DATE_UL, "Invalid Date")
210211
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_APPLY, "apply")
211212
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CALL, "call")
212213
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BIND, "bind")
@@ -217,6 +218,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MESSAGE, "message")
217218
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_G_CHAR, "g")
218219
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_I_CHAR, "i")
219220
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_M_CHAR, "m")
221+
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TIME_SEP_U, "T")
220222
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SLASH_CHAR, "/")
221223
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BACKSLASH_CHAR, "\\")
222224
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP, "(?:)")
@@ -227,6 +229,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RIGHT_BRACE_CHAR, "}")
227229
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MINUS_CHAR, "-")
228230
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COLON_CHAR, ":")
229231
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMMA_CHAR, ",")
232+
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DOT_CHAR, ".")
230233
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DOUBLE_QUOTE_CHAR, "\"")
231234
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NEW_LINE_CHAR, "\n")
232235
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPACE_CHAR, " ")

tests/jerry/date-tostring.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2015 Samsung Electronics Co., Ltd.
2+
// Copyright 2015 University of Szeged.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
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");

0 commit comments

Comments
 (0)