-
Notifications
You must be signed in to change notification settings - Fork 683
Implement Date.prototype.toDateString and Date.prototype.toTimeString #360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,7 +53,9 @@ ecma_date_insert_leading_zeros (ecma_string_t **str_p, /**< input/output string | |
JERRY_ASSERT (length >= 1); | ||
|
||
/* If the length is bigger than the number of digits in num, then insert leding zeros. */ | ||
for (uint32_t i = length - 1; i > 0 && num < pow (10,i); i--) | ||
uint32_t first_index = length - 1u; | ||
ecma_number_t power_i = (ecma_number_t) pow (10, first_index); | ||
for (uint32_t i = first_index; i > 0 && num < power_i; i--, power_i /= 10) | ||
{ | ||
ecma_string_t *zero_str_p = ecma_new_ecma_string_from_uint32 (0); | ||
ecma_string_t *concat_p = ecma_concat_ecma_strings (zero_str_p, *str_p); | ||
|
@@ -103,9 +105,10 @@ ecma_builtin_date_prototype_to_string (ecma_value_t this_arg) /**< this argument | |
{ | ||
ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); | ||
|
||
if (ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_DATE_UL) | ||
if (!ecma_is_value_object (this_arg) | ||
|| ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_DATE_UL) | ||
{ | ||
ret_value = ecma_raise_type_error ("Incomplete Date type"); | ||
ret_value = ecma_raise_type_error ("Incompatible type"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As actions under the conditions of the if and else if blocks are the same, and conditions are not complex, it is better to merge the blocks. |
||
} | ||
else | ||
{ | ||
|
@@ -174,7 +177,54 @@ ecma_builtin_date_prototype_to_string (ecma_value_t this_arg) /**< this argument | |
static ecma_completion_value_t | ||
ecma_builtin_date_prototype_to_date_string (ecma_value_t this_arg) /**< this argument */ | ||
{ | ||
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg); | ||
ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); | ||
|
||
if (!ecma_is_value_object (this_arg) | ||
|| ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_DATE_UL) | ||
{ | ||
ret_value = ecma_raise_type_error ("Incompatible type"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likewise. |
||
} | ||
else | ||
{ | ||
ECMA_TRY_CATCH (obj_this, | ||
ecma_op_to_object (this_arg), | ||
ret_value); | ||
|
||
ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); | ||
ecma_property_t *prim_value_prop_p; | ||
prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); | ||
ecma_number_t *prim_value_num_p = ECMA_GET_NON_NULL_POINTER (ecma_number_t, | ||
prim_value_prop_p->u.internal_property.value); | ||
|
||
if (ecma_number_is_nan (*prim_value_num_p)) | ||
{ | ||
ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INVALID_DATE_UL); | ||
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (magic_str_p)); | ||
} | ||
else | ||
{ | ||
ecma_number_t day = ecma_date_date_from_time (*prim_value_num_p); | ||
ecma_string_t *output_str_p = ecma_new_ecma_string_from_number (day); | ||
ecma_date_insert_leading_zeros (&output_str_p, day, 2); | ||
|
||
/* | ||
* 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 (*prim_value_num_p) + 1; | ||
ecma_date_insert_num_with_sep (&output_str_p, month, LIT_MAGIC_STRING_MINUS_CHAR, 2); | ||
|
||
ecma_number_t year = ecma_date_year_from_time (*prim_value_num_p); | ||
ecma_date_insert_num_with_sep (&output_str_p, year, LIT_MAGIC_STRING_MINUS_CHAR, 4); | ||
|
||
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (output_str_p)); | ||
} | ||
|
||
ECMA_FINALIZE (obj_this); | ||
} | ||
|
||
return ret_value; | ||
} /* ecma_builtin_date_prototype_to_date_string */ | ||
|
||
/** | ||
|
@@ -189,7 +239,52 @@ ecma_builtin_date_prototype_to_date_string (ecma_value_t this_arg) /**< this arg | |
static ecma_completion_value_t | ||
ecma_builtin_date_prototype_to_time_string (ecma_value_t this_arg) /**< this argument */ | ||
{ | ||
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg); | ||
ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); | ||
|
||
if (!ecma_is_value_object (this_arg) | ||
|| ecma_object_get_class_name (ecma_get_object_from_value (this_arg)) != LIT_MAGIC_STRING_DATE_UL) | ||
{ | ||
ret_value = ecma_raise_type_error ("Incompatible type"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likewise. |
||
} | ||
else | ||
{ | ||
ECMA_TRY_CATCH (obj_this, | ||
ecma_op_to_object (this_arg), | ||
ret_value); | ||
|
||
ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); | ||
ecma_property_t *prim_value_prop_p; | ||
prim_value_prop_p = ecma_get_internal_property (obj_p, ECMA_INTERNAL_PROPERTY_PRIMITIVE_NUMBER_VALUE); | ||
ecma_number_t *prim_value_num_p = ECMA_GET_NON_NULL_POINTER (ecma_number_t, | ||
prim_value_prop_p->u.internal_property.value); | ||
|
||
if (ecma_number_is_nan (*prim_value_num_p)) | ||
{ | ||
ecma_string_t *magic_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_INVALID_DATE_UL); | ||
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (magic_str_p)); | ||
} | ||
else | ||
{ | ||
ecma_number_t milliseconds = ecma_date_ms_from_time (*prim_value_num_p); | ||
ecma_string_t *output_str_p = ecma_new_ecma_string_from_number (milliseconds); | ||
ecma_date_insert_leading_zeros (&output_str_p, milliseconds, 3); | ||
|
||
ecma_number_t seconds = ecma_date_sec_from_time (*prim_value_num_p); | ||
ecma_date_insert_num_with_sep (&output_str_p, seconds, LIT_MAGIC_STRING_DOT_CHAR, 2); | ||
|
||
ecma_number_t minutes = ecma_date_min_from_time (*prim_value_num_p); | ||
ecma_date_insert_num_with_sep (&output_str_p, minutes, LIT_MAGIC_STRING_COLON_CHAR, 2); | ||
|
||
ecma_number_t hours = ecma_date_hour_from_time (*prim_value_num_p); | ||
ecma_date_insert_num_with_sep (&output_str_p, hours, LIT_MAGIC_STRING_COLON_CHAR, 2); | ||
|
||
ret_value = ecma_make_normal_completion_value (ecma_make_string_value (output_str_p)); | ||
} | ||
|
||
ECMA_FINALIZE (obj_this); | ||
} | ||
|
||
return ret_value; | ||
} /* ecma_builtin_date_prototype_to_time_string */ | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,47 @@ | |
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
assert (new Date(NaN) == "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 (NaN) == "Invalid Date"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why don't we use 3 equal signs? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I always write tests like this. :) Should I change this? Why would be 3 equal signs better? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because it also checks the type, so it is more strict than the two. I would recommend to use it in the future. Later you can make a style patch to change these. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, thanks for explain. I'll raise an issue for this. |
||
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"); | ||
|
||
try | ||
{ | ||
Date.prototype.toString.call(-1); | ||
assert (false); | ||
} | ||
catch (e) | ||
{ | ||
assert (e instanceof TypeError); | ||
assert (e.message === "Incompatible type"); | ||
} | ||
|
||
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"); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need test cases for the TypeError also. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added |
||
try | ||
{ | ||
Date.prototype.toDateString.call(-1); | ||
assert (false); | ||
} | ||
catch (e) | ||
{ | ||
assert (e instanceof TypeError); | ||
assert (e.message === "Incompatible type"); | ||
} | ||
|
||
assert (new Date (NaN).toTimeString () == "Invalid Date"); | ||
assert (new Date ("2015-02-13").toTimeString () == "00:00:00.000"); | ||
assert (new Date ("2015-07-08T11:29:05.023").toTimeString () == "11:29:05.023"); | ||
|
||
try | ||
{ | ||
Date.prototype.toTimeString.call(-1); | ||
assert (false); | ||
} | ||
catch (e) | ||
{ | ||
assert (e instanceof TypeError); | ||
assert (e.message === "Incompatible type"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the range of length? I mean what happens if power_i cannot precisely represent the value? Is that possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No it is not possible, the range is 1-4.