1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci */
15425bb815Sopenharmony_ci
16425bb815Sopenharmony_ci#include <math.h>
17425bb815Sopenharmony_ci
18425bb815Sopenharmony_ci#include "jcontext.h"
19425bb815Sopenharmony_ci#include "ecma-function-object.h"
20425bb815Sopenharmony_ci#include "ecma-alloc.h"
21425bb815Sopenharmony_ci#include "ecma-builtin-helpers.h"
22425bb815Sopenharmony_ci#include "ecma-conversion.h"
23425bb815Sopenharmony_ci#include "ecma-exceptions.h"
24425bb815Sopenharmony_ci#include "ecma-gc.h"
25425bb815Sopenharmony_ci#include "ecma-globals.h"
26425bb815Sopenharmony_ci#include "ecma-helpers.h"
27425bb815Sopenharmony_ci#include "ecma-try-catch-macro.h"
28425bb815Sopenharmony_ci#include "lit-char-helpers.h"
29425bb815Sopenharmony_ci
30425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_DATE)
31425bb815Sopenharmony_ci
32425bb815Sopenharmony_ci#define ECMA_BUILTINS_INTERNAL
33425bb815Sopenharmony_ci#include "ecma-builtins-internal.h"
34425bb815Sopenharmony_ci
35425bb815Sopenharmony_ci#define BUILTIN_INC_HEADER_NAME "ecma-builtin-date.inc.h"
36425bb815Sopenharmony_ci#define BUILTIN_UNDERSCORED_ID date
37425bb815Sopenharmony_ci#include "ecma-builtin-internal-routines-template.inc.h"
38425bb815Sopenharmony_ci
39425bb815Sopenharmony_ci/** \addtogroup ecma ECMA
40425bb815Sopenharmony_ci * @{
41425bb815Sopenharmony_ci *
42425bb815Sopenharmony_ci * \addtogroup ecmabuiltins
43425bb815Sopenharmony_ci * @{
44425bb815Sopenharmony_ci *
45425bb815Sopenharmony_ci * \addtogroup date ECMA Date object built-in
46425bb815Sopenharmony_ci * @{
47425bb815Sopenharmony_ci */
48425bb815Sopenharmony_ci
49425bb815Sopenharmony_ci/**
50425bb815Sopenharmony_ci * Helper function to try to parse a part of a date string
51425bb815Sopenharmony_ci *
52425bb815Sopenharmony_ci * @return NaN if cannot read from string, ToNumber() otherwise
53425bb815Sopenharmony_ci */
54425bb815Sopenharmony_cistatic ecma_number_t
55425bb815Sopenharmony_ciecma_date_parse_date_chars (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */
56425bb815Sopenharmony_ci                            const lit_utf8_byte_t *str_end_p, /**< pointer to the end of the string */
57425bb815Sopenharmony_ci                            uint32_t num_of_chars, /**< number of characters to read and convert */
58425bb815Sopenharmony_ci                            uint32_t min, /**< minimum valid value */
59425bb815Sopenharmony_ci                            uint32_t max) /**< maximum valid value */
60425bb815Sopenharmony_ci{
61425bb815Sopenharmony_ci  JERRY_ASSERT (num_of_chars > 0);
62425bb815Sopenharmony_ci  const lit_utf8_byte_t *str_start_p = *str_p;
63425bb815Sopenharmony_ci
64425bb815Sopenharmony_ci  while (num_of_chars--)
65425bb815Sopenharmony_ci  {
66425bb815Sopenharmony_ci    if (*str_p >= str_end_p || !lit_char_is_decimal_digit (lit_cesu8_read_next (str_p)))
67425bb815Sopenharmony_ci    {
68425bb815Sopenharmony_ci      return ecma_number_make_nan ();
69425bb815Sopenharmony_ci    }
70425bb815Sopenharmony_ci  }
71425bb815Sopenharmony_ci
72425bb815Sopenharmony_ci  ecma_number_t parsed_number = ecma_utf8_string_to_number (str_start_p, (lit_utf8_size_t) (*str_p - str_start_p));
73425bb815Sopenharmony_ci
74425bb815Sopenharmony_ci  if (parsed_number < min || parsed_number > max)
75425bb815Sopenharmony_ci  {
76425bb815Sopenharmony_ci    return ecma_number_make_nan ();
77425bb815Sopenharmony_ci  }
78425bb815Sopenharmony_ci
79425bb815Sopenharmony_ci  return parsed_number;
80425bb815Sopenharmony_ci} /* ecma_date_parse_date_chars */
81425bb815Sopenharmony_ci
82425bb815Sopenharmony_ci/**
83425bb815Sopenharmony_ci * Helper function to try to parse a special chracter (+,-,T,Z,:,.) in a date string
84425bb815Sopenharmony_ci *
85425bb815Sopenharmony_ci * @return true if the first character is same as the expected, false otherwise
86425bb815Sopenharmony_ci */
87425bb815Sopenharmony_cistatic bool
88425bb815Sopenharmony_ciecma_date_parse_special_char (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */
89425bb815Sopenharmony_ci                              const lit_utf8_byte_t *str_end_p, /**< pointer to the end of the string */
90425bb815Sopenharmony_ci                              const lit_utf8_byte_t expected_char) /**< expected character */
91425bb815Sopenharmony_ci{
92425bb815Sopenharmony_ci  if ((*str_p < str_end_p) && (**str_p == expected_char))
93425bb815Sopenharmony_ci  {
94425bb815Sopenharmony_ci    (*str_p)++;
95425bb815Sopenharmony_ci    return true;
96425bb815Sopenharmony_ci  }
97425bb815Sopenharmony_ci
98425bb815Sopenharmony_ci  return false;
99425bb815Sopenharmony_ci} /* ecma_date_parse_special_char */
100425bb815Sopenharmony_ci
101425bb815Sopenharmony_ci/**
102425bb815Sopenharmony_ci * Helper function to try to parse a 4-5-6 digit year with optional negative sign in a date string
103425bb815Sopenharmony_ci *
104425bb815Sopenharmony_ci * Date.prototype.toString() and Date.prototype.toUTCString() emits year
105425bb815Sopenharmony_ci * in this format and Date.parse() should parse this format too.
106425bb815Sopenharmony_ci *
107425bb815Sopenharmony_ci * @return the parsed year or NaN.
108425bb815Sopenharmony_ci */
109425bb815Sopenharmony_cistatic ecma_number_t
110425bb815Sopenharmony_ciecma_date_parse_year (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */
111425bb815Sopenharmony_ci                      const lit_utf8_byte_t *str_end_p) /**< pointer to the end of the string */
112425bb815Sopenharmony_ci{
113425bb815Sopenharmony_ci  bool is_year_sign_negative = ecma_date_parse_special_char (str_p, str_end_p, '-');
114425bb815Sopenharmony_ci  const lit_utf8_byte_t *str_start_p = *str_p;
115425bb815Sopenharmony_ci  int32_t parsed_year = 0;
116425bb815Sopenharmony_ci
117425bb815Sopenharmony_ci  while ((str_start_p - *str_p < 6) && (str_start_p < str_end_p) && lit_char_is_decimal_digit (*str_start_p))
118425bb815Sopenharmony_ci  {
119425bb815Sopenharmony_ci    parsed_year = 10 * parsed_year + *str_start_p - LIT_CHAR_0;
120425bb815Sopenharmony_ci    str_start_p++;
121425bb815Sopenharmony_ci  }
122425bb815Sopenharmony_ci
123425bb815Sopenharmony_ci  if (str_start_p - *str_p >=4)
124425bb815Sopenharmony_ci  {
125425bb815Sopenharmony_ci    *str_p = str_start_p;
126425bb815Sopenharmony_ci    if (is_year_sign_negative)
127425bb815Sopenharmony_ci    {
128425bb815Sopenharmony_ci      return -parsed_year;
129425bb815Sopenharmony_ci    }
130425bb815Sopenharmony_ci    return parsed_year;
131425bb815Sopenharmony_ci  }
132425bb815Sopenharmony_ci
133425bb815Sopenharmony_ci  return ecma_number_make_nan ();
134425bb815Sopenharmony_ci} /* ecma_date_parse_year */
135425bb815Sopenharmony_ci
136425bb815Sopenharmony_ci/**
137425bb815Sopenharmony_ci * Helper function to try to parse a day name in a date string
138425bb815Sopenharmony_ci * Valid day names: Sun, Mon, Tue, Wed, Thu, Fri, Sat
139425bb815Sopenharmony_ci * See also:
140425bb815Sopenharmony_ci *          ECMA-262 v9, 20.3.4.41.2 Table 46
141425bb815Sopenharmony_ci *
142425bb815Sopenharmony_ci * @return true if the string starts with a valid day name, false otherwise
143425bb815Sopenharmony_ci */
144425bb815Sopenharmony_cistatic bool
145425bb815Sopenharmony_ciecma_date_parse_day_name (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */
146425bb815Sopenharmony_ci                          const lit_utf8_byte_t *str_end_p) /**< pointer to the end of the string */
147425bb815Sopenharmony_ci{
148425bb815Sopenharmony_ci  if (*str_p + 3 < str_end_p)
149425bb815Sopenharmony_ci  {
150425bb815Sopenharmony_ci    for (uint32_t i = 0; i < 7; i++)
151425bb815Sopenharmony_ci    {
152425bb815Sopenharmony_ci      if (!memcmp (day_names_p[i], *str_p, 3))
153425bb815Sopenharmony_ci      {
154425bb815Sopenharmony_ci        (*str_p) += 3;
155425bb815Sopenharmony_ci        return true;
156425bb815Sopenharmony_ci      }
157425bb815Sopenharmony_ci    }
158425bb815Sopenharmony_ci  }
159425bb815Sopenharmony_ci  return false;
160425bb815Sopenharmony_ci} /* ecma_date_parse_day_name */
161425bb815Sopenharmony_ci
162425bb815Sopenharmony_ci/**
163425bb815Sopenharmony_ci * Helper function to try to parse a month name in a date string
164425bb815Sopenharmony_ci * Valid month names: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
165425bb815Sopenharmony_ci * See also:
166425bb815Sopenharmony_ci *          ECMA-262 v9, 20.3.4.41.2 Table 47
167425bb815Sopenharmony_ci *
168425bb815Sopenharmony_ci * @return number of the month if the string starts with a valid month name, 0 otherwise
169425bb815Sopenharmony_ci */
170425bb815Sopenharmony_cistatic uint32_t
171425bb815Sopenharmony_ciecma_date_parse_month_name (const lit_utf8_byte_t **str_p, /**< pointer to the cesu8 string */
172425bb815Sopenharmony_ci                            const lit_utf8_byte_t *str_end_p) /**< pointer to the end of the string */
173425bb815Sopenharmony_ci{
174425bb815Sopenharmony_ci  if (*str_p + 3 < str_end_p)
175425bb815Sopenharmony_ci  {
176425bb815Sopenharmony_ci    for (uint32_t i = 0; i < 12; i++)
177425bb815Sopenharmony_ci    {
178425bb815Sopenharmony_ci      if (!memcmp (month_names_p[i], *str_p, 3))
179425bb815Sopenharmony_ci      {
180425bb815Sopenharmony_ci        (*str_p) += 3;
181425bb815Sopenharmony_ci        return (i+1);
182425bb815Sopenharmony_ci      }
183425bb815Sopenharmony_ci    }
184425bb815Sopenharmony_ci  }
185425bb815Sopenharmony_ci  return 0;
186425bb815Sopenharmony_ci} /* ecma_date_parse_month_name */
187425bb815Sopenharmony_ci
188425bb815Sopenharmony_ci/**
189425bb815Sopenharmony_ci  * Calculate MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)) for Date constructor and UTC
190425bb815Sopenharmony_ci  *
191425bb815Sopenharmony_ci  * See also:
192425bb815Sopenharmony_ci  *          ECMA-262 v5, 15.9.3.1
193425bb815Sopenharmony_ci  *          ECMA-262 v5, 15.9.4.3
194425bb815Sopenharmony_ci  *
195425bb815Sopenharmony_ci  * @return result of MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli))
196425bb815Sopenharmony_ci  */
197425bb815Sopenharmony_cistatic ecma_value_t
198425bb815Sopenharmony_ciecma_date_construct_helper (const ecma_value_t *args, /**< arguments passed to the Date constructor */
199425bb815Sopenharmony_ci                            ecma_length_t args_len) /**< number of arguments */
200425bb815Sopenharmony_ci{
201425bb815Sopenharmony_ci  ecma_value_t ret_value = ECMA_VALUE_EMPTY;
202425bb815Sopenharmony_ci  ecma_number_t prim_value = ecma_number_make_nan ();
203425bb815Sopenharmony_ci
204425bb815Sopenharmony_ci  ECMA_TRY_CATCH (year_value, ecma_op_to_number (args[0]), ret_value);
205425bb815Sopenharmony_ci  ECMA_TRY_CATCH (month_value, ecma_op_to_number (args[1]), ret_value);
206425bb815Sopenharmony_ci
207425bb815Sopenharmony_ci  ecma_number_t year = ecma_get_number_from_value (year_value);
208425bb815Sopenharmony_ci  ecma_number_t month = ecma_get_number_from_value (month_value);
209425bb815Sopenharmony_ci  ecma_number_t date = ECMA_NUMBER_ONE;
210425bb815Sopenharmony_ci  ecma_number_t hours = ECMA_NUMBER_ZERO;
211425bb815Sopenharmony_ci  ecma_number_t minutes = ECMA_NUMBER_ZERO;
212425bb815Sopenharmony_ci  ecma_number_t seconds = ECMA_NUMBER_ZERO;
213425bb815Sopenharmony_ci  ecma_number_t milliseconds = ECMA_NUMBER_ZERO;
214425bb815Sopenharmony_ci
215425bb815Sopenharmony_ci  /* 3. */
216425bb815Sopenharmony_ci  if (args_len >= 3 && ecma_is_value_empty (ret_value))
217425bb815Sopenharmony_ci  {
218425bb815Sopenharmony_ci    ECMA_TRY_CATCH (date_value, ecma_op_to_number (args[2]), ret_value);
219425bb815Sopenharmony_ci    date = ecma_get_number_from_value (date_value);
220425bb815Sopenharmony_ci    ECMA_FINALIZE (date_value);
221425bb815Sopenharmony_ci  }
222425bb815Sopenharmony_ci
223425bb815Sopenharmony_ci  /* 4. */
224425bb815Sopenharmony_ci  if (args_len >= 4 && ecma_is_value_empty (ret_value))
225425bb815Sopenharmony_ci  {
226425bb815Sopenharmony_ci    ECMA_TRY_CATCH (hours_value, ecma_op_to_number (args[3]), ret_value);
227425bb815Sopenharmony_ci    hours = ecma_get_number_from_value (hours_value);
228425bb815Sopenharmony_ci    ECMA_FINALIZE (hours_value);
229425bb815Sopenharmony_ci  }
230425bb815Sopenharmony_ci
231425bb815Sopenharmony_ci  /* 5. */
232425bb815Sopenharmony_ci  if (args_len >= 5 && ecma_is_value_empty (ret_value))
233425bb815Sopenharmony_ci  {
234425bb815Sopenharmony_ci    ECMA_TRY_CATCH (minutes_value, ecma_op_to_number (args[4]), ret_value);
235425bb815Sopenharmony_ci    minutes = ecma_get_number_from_value (minutes_value);
236425bb815Sopenharmony_ci    ECMA_FINALIZE (minutes_value);
237425bb815Sopenharmony_ci  }
238425bb815Sopenharmony_ci
239425bb815Sopenharmony_ci  /* 6. */
240425bb815Sopenharmony_ci  if (args_len >= 6 && ecma_is_value_empty (ret_value))
241425bb815Sopenharmony_ci  {
242425bb815Sopenharmony_ci    ECMA_TRY_CATCH (seconds_value, ecma_op_to_number (args[5]), ret_value);
243425bb815Sopenharmony_ci    seconds = ecma_get_number_from_value (seconds_value);
244425bb815Sopenharmony_ci    ECMA_FINALIZE (seconds_value);
245425bb815Sopenharmony_ci  }
246425bb815Sopenharmony_ci
247425bb815Sopenharmony_ci  /* 7. */
248425bb815Sopenharmony_ci  if (args_len >= 7 && ecma_is_value_empty (ret_value))
249425bb815Sopenharmony_ci  {
250425bb815Sopenharmony_ci    ECMA_TRY_CATCH (milliseconds_value, ecma_op_to_number (args[6]), ret_value);
251425bb815Sopenharmony_ci    milliseconds = ecma_get_number_from_value (milliseconds_value);
252425bb815Sopenharmony_ci    ECMA_FINALIZE (milliseconds_value);
253425bb815Sopenharmony_ci  }
254425bb815Sopenharmony_ci
255425bb815Sopenharmony_ci  if (ecma_is_value_empty (ret_value))
256425bb815Sopenharmony_ci  {
257425bb815Sopenharmony_ci    if (!ecma_number_is_nan (year))
258425bb815Sopenharmony_ci    {
259425bb815Sopenharmony_ci      /* 8. */
260425bb815Sopenharmony_ci      ecma_number_t y = ecma_number_trunc (year);
261425bb815Sopenharmony_ci
262425bb815Sopenharmony_ci      if (y >= 0 && y <= 99)
263425bb815Sopenharmony_ci      {
264425bb815Sopenharmony_ci        year = 1900 + y;
265425bb815Sopenharmony_ci      }
266425bb815Sopenharmony_ci    }
267425bb815Sopenharmony_ci
268425bb815Sopenharmony_ci    prim_value = ecma_date_make_date (ecma_date_make_day (year,
269425bb815Sopenharmony_ci                                                          month,
270425bb815Sopenharmony_ci                                                          date),
271425bb815Sopenharmony_ci                                      ecma_date_make_time (hours,
272425bb815Sopenharmony_ci                                                           minutes,
273425bb815Sopenharmony_ci                                                           seconds,
274425bb815Sopenharmony_ci                                                           milliseconds));
275425bb815Sopenharmony_ci  }
276425bb815Sopenharmony_ci
277425bb815Sopenharmony_ci  ECMA_FINALIZE (month_value);
278425bb815Sopenharmony_ci  ECMA_FINALIZE (year_value);
279425bb815Sopenharmony_ci
280425bb815Sopenharmony_ci  if (ecma_is_value_empty (ret_value))
281425bb815Sopenharmony_ci  {
282425bb815Sopenharmony_ci    ret_value = ecma_make_number_value (prim_value);
283425bb815Sopenharmony_ci  }
284425bb815Sopenharmony_ci
285425bb815Sopenharmony_ci  return ret_value;
286425bb815Sopenharmony_ci} /* ecma_date_construct_helper */
287425bb815Sopenharmony_ci
288425bb815Sopenharmony_ci/**
289425bb815Sopenharmony_ci * Helper function used by ecma_builtin_date_parse
290425bb815Sopenharmony_ci *
291425bb815Sopenharmony_ci * See also:
292425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.4.2  Date.parse (string)
293425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.15 Date Time String Format
294425bb815Sopenharmony_ci *
295425bb815Sopenharmony_ci * @return the parsed date as ecma_number_t or NaN otherwise
296425bb815Sopenharmony_ci */
297425bb815Sopenharmony_cistatic ecma_number_t
298425bb815Sopenharmony_ciecma_builtin_date_parse_ISO_string_format (const lit_utf8_byte_t *date_str_curr_p,
299425bb815Sopenharmony_ci                                           const lit_utf8_byte_t *date_str_end_p)
300425bb815Sopenharmony_ci{
301425bb815Sopenharmony_ci  /* 1. read year */
302425bb815Sopenharmony_ci
303425bb815Sopenharmony_ci  uint32_t year_digits = 4;
304425bb815Sopenharmony_ci
305425bb815Sopenharmony_ci  bool is_year_sign_negative = ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, '-');
306425bb815Sopenharmony_ci  if (is_year_sign_negative || ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, '+'))
307425bb815Sopenharmony_ci  {
308425bb815Sopenharmony_ci    year_digits = 6;
309425bb815Sopenharmony_ci  }
310425bb815Sopenharmony_ci
311425bb815Sopenharmony_ci  ecma_number_t year = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, year_digits,
312425bb815Sopenharmony_ci                                                   0, (year_digits == 4) ? 9999 : 999999);
313425bb815Sopenharmony_ci  if (is_year_sign_negative)
314425bb815Sopenharmony_ci  {
315425bb815Sopenharmony_ci    year = -year;
316425bb815Sopenharmony_ci  }
317425bb815Sopenharmony_ci
318425bb815Sopenharmony_ci  if (!ecma_number_is_nan (year))
319425bb815Sopenharmony_ci  {
320425bb815Sopenharmony_ci    ecma_number_t month = ECMA_NUMBER_ONE;
321425bb815Sopenharmony_ci    ecma_number_t day = ECMA_NUMBER_ONE;
322425bb815Sopenharmony_ci    ecma_number_t time = ECMA_NUMBER_ZERO;
323425bb815Sopenharmony_ci
324425bb815Sopenharmony_ci    /* 2. read month if any */
325425bb815Sopenharmony_ci    if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, '-'))
326425bb815Sopenharmony_ci    {
327425bb815Sopenharmony_ci      month = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 1, 12);
328425bb815Sopenharmony_ci    }
329425bb815Sopenharmony_ci
330425bb815Sopenharmony_ci    /* 3. read day if any */
331425bb815Sopenharmony_ci    if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, '-'))
332425bb815Sopenharmony_ci    {
333425bb815Sopenharmony_ci      day = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 1, 31);
334425bb815Sopenharmony_ci    }
335425bb815Sopenharmony_ci
336425bb815Sopenharmony_ci    /* 4. read time if any */
337425bb815Sopenharmony_ci    if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, 'T'))
338425bb815Sopenharmony_ci    {
339425bb815Sopenharmony_ci      ecma_number_t hours = ECMA_NUMBER_ZERO;
340425bb815Sopenharmony_ci      ecma_number_t minutes = ECMA_NUMBER_ZERO;
341425bb815Sopenharmony_ci      ecma_number_t seconds = ECMA_NUMBER_ZERO;
342425bb815Sopenharmony_ci      ecma_number_t milliseconds = ECMA_NUMBER_ZERO;
343425bb815Sopenharmony_ci
344425bb815Sopenharmony_ci      ecma_length_t remaining_length = lit_utf8_string_length (date_str_curr_p,
345425bb815Sopenharmony_ci                                                               (lit_utf8_size_t) (date_str_end_p - date_str_curr_p));
346425bb815Sopenharmony_ci
347425bb815Sopenharmony_ci      if (remaining_length >= 5)
348425bb815Sopenharmony_ci      {
349425bb815Sopenharmony_ci        /* 4.1 read hours and minutes */
350425bb815Sopenharmony_ci        hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 24);
351425bb815Sopenharmony_ci
352425bb815Sopenharmony_ci        if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ':'))
353425bb815Sopenharmony_ci        {
354425bb815Sopenharmony_ci          minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 59);
355425bb815Sopenharmony_ci
356425bb815Sopenharmony_ci          /* 4.2 read seconds if any */
357425bb815Sopenharmony_ci          if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ':'))
358425bb815Sopenharmony_ci          {
359425bb815Sopenharmony_ci            seconds = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 59);
360425bb815Sopenharmony_ci
361425bb815Sopenharmony_ci            /* 4.3 read milliseconds if any */
362425bb815Sopenharmony_ci            if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, '.'))
363425bb815Sopenharmony_ci            {
364425bb815Sopenharmony_ci              milliseconds = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 3, 0, 999);
365425bb815Sopenharmony_ci            }
366425bb815Sopenharmony_ci          }
367425bb815Sopenharmony_ci        }
368425bb815Sopenharmony_ci        else
369425bb815Sopenharmony_ci        {
370425bb815Sopenharmony_ci          minutes = ecma_number_make_nan ();
371425bb815Sopenharmony_ci        }
372425bb815Sopenharmony_ci
373425bb815Sopenharmony_ci        if (hours == 24 && (minutes != 0 || seconds != 0 || milliseconds != 0))
374425bb815Sopenharmony_ci        {
375425bb815Sopenharmony_ci          hours = ecma_number_make_nan ();
376425bb815Sopenharmony_ci        }
377425bb815Sopenharmony_ci
378425bb815Sopenharmony_ci        time = ecma_date_make_time (hours, minutes, seconds, milliseconds);
379425bb815Sopenharmony_ci      }
380425bb815Sopenharmony_ci      else
381425bb815Sopenharmony_ci      {
382425bb815Sopenharmony_ci        time = ecma_number_make_nan ();
383425bb815Sopenharmony_ci      }
384425bb815Sopenharmony_ci
385425bb815Sopenharmony_ci      /* 4.4 read timezone if any */
386425bb815Sopenharmony_ci      if (ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, 'Z') && !ecma_number_is_nan (time))
387425bb815Sopenharmony_ci      {
388425bb815Sopenharmony_ci        time = ecma_date_make_time (hours, minutes, seconds, milliseconds);
389425bb815Sopenharmony_ci      }
390425bb815Sopenharmony_ci      else
391425bb815Sopenharmony_ci      {
392425bb815Sopenharmony_ci        bool is_timezone_sign_negative;
393425bb815Sopenharmony_ci        if ((lit_utf8_string_length (date_str_curr_p, (lit_utf8_size_t) (date_str_end_p - date_str_curr_p)) == 6)
394425bb815Sopenharmony_ci            && ((is_timezone_sign_negative = ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, '-'))
395425bb815Sopenharmony_ci            || ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, '+')))
396425bb815Sopenharmony_ci        {
397425bb815Sopenharmony_ci          /* read hours and minutes */
398425bb815Sopenharmony_ci          hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 24);
399425bb815Sopenharmony_ci
400425bb815Sopenharmony_ci          if (hours == 24)
401425bb815Sopenharmony_ci          {
402425bb815Sopenharmony_ci            hours = ECMA_NUMBER_ZERO;
403425bb815Sopenharmony_ci          }
404425bb815Sopenharmony_ci
405425bb815Sopenharmony_ci          ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ':');
406425bb815Sopenharmony_ci          minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 59);
407425bb815Sopenharmony_ci          ecma_number_t timezone_offset = ecma_date_make_time (hours, minutes, ECMA_NUMBER_ZERO, ECMA_NUMBER_ZERO);
408425bb815Sopenharmony_ci          time += is_timezone_sign_negative ? timezone_offset : -timezone_offset;
409425bb815Sopenharmony_ci        }
410425bb815Sopenharmony_ci      }
411425bb815Sopenharmony_ci    }
412425bb815Sopenharmony_ci
413425bb815Sopenharmony_ci    if (date_str_curr_p >= date_str_end_p)
414425bb815Sopenharmony_ci    {
415425bb815Sopenharmony_ci      ecma_number_t date = ecma_date_make_day (year, month - 1, day);
416425bb815Sopenharmony_ci      return ecma_date_make_date (date, time);
417425bb815Sopenharmony_ci    }
418425bb815Sopenharmony_ci  }
419425bb815Sopenharmony_ci  return ecma_number_make_nan ();
420425bb815Sopenharmony_ci} /* ecma_builtin_date_parse_ISO_string_format */
421425bb815Sopenharmony_ci
422425bb815Sopenharmony_ci/**
423425bb815Sopenharmony_ci * Helper function used by ecma_builtin_date_parse
424425bb815Sopenharmony_ci *
425425bb815Sopenharmony_ci * See also:
426425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.4.2  Date.parse (string)
427425bb815Sopenharmony_ci *          ECMA-262 v9, 20.3.4.41 Date.prototype.toString ()
428425bb815Sopenharmony_ci *          ECMA-262 v9, 20.3.4.43 Date.prototype.toUTCString ()
429425bb815Sopenharmony_ci *
430425bb815Sopenharmony_ci * Used by: ecma_builtin_date_parse
431425bb815Sopenharmony_ci *
432425bb815Sopenharmony_ci * @return the parsed date as ecma_number_t or NaN otherwise
433425bb815Sopenharmony_ci */
434425bb815Sopenharmony_cistatic ecma_number_t
435425bb815Sopenharmony_ciecma_builtin_date_parse_toString_formats (const lit_utf8_byte_t *date_str_curr_p,
436425bb815Sopenharmony_ci                                          const lit_utf8_byte_t *date_str_end_p)
437425bb815Sopenharmony_ci{
438425bb815Sopenharmony_ci  const ecma_number_t nan = ecma_number_make_nan ();
439425bb815Sopenharmony_ci
440425bb815Sopenharmony_ci  if (!ecma_date_parse_day_name (&date_str_curr_p, date_str_end_p))
441425bb815Sopenharmony_ci  {
442425bb815Sopenharmony_ci    return nan;
443425bb815Sopenharmony_ci  }
444425bb815Sopenharmony_ci
445425bb815Sopenharmony_ci  const bool is_toUTCString_format = ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ',');
446425bb815Sopenharmony_ci
447425bb815Sopenharmony_ci  if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ' '))
448425bb815Sopenharmony_ci  {
449425bb815Sopenharmony_ci    return nan;
450425bb815Sopenharmony_ci  }
451425bb815Sopenharmony_ci
452425bb815Sopenharmony_ci  ecma_number_t month = 0;
453425bb815Sopenharmony_ci  ecma_number_t day = 0;
454425bb815Sopenharmony_ci  if (is_toUTCString_format)
455425bb815Sopenharmony_ci  {
456425bb815Sopenharmony_ci    day = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 31);
457425bb815Sopenharmony_ci    if (ecma_number_is_nan (day))
458425bb815Sopenharmony_ci    {
459425bb815Sopenharmony_ci      return nan;
460425bb815Sopenharmony_ci    }
461425bb815Sopenharmony_ci
462425bb815Sopenharmony_ci    if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ' '))
463425bb815Sopenharmony_ci    {
464425bb815Sopenharmony_ci      return nan;
465425bb815Sopenharmony_ci    }
466425bb815Sopenharmony_ci
467425bb815Sopenharmony_ci    month = ecma_date_parse_month_name (&date_str_curr_p, date_str_end_p);
468425bb815Sopenharmony_ci    if (!(int) month)
469425bb815Sopenharmony_ci    {
470425bb815Sopenharmony_ci      return nan;
471425bb815Sopenharmony_ci    }
472425bb815Sopenharmony_ci  }
473425bb815Sopenharmony_ci  else
474425bb815Sopenharmony_ci  {
475425bb815Sopenharmony_ci    month = ecma_date_parse_month_name (&date_str_curr_p, date_str_end_p);
476425bb815Sopenharmony_ci    if (!(int) month)
477425bb815Sopenharmony_ci    {
478425bb815Sopenharmony_ci      return nan;
479425bb815Sopenharmony_ci    }
480425bb815Sopenharmony_ci
481425bb815Sopenharmony_ci    if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ' '))
482425bb815Sopenharmony_ci    {
483425bb815Sopenharmony_ci      return nan;
484425bb815Sopenharmony_ci    }
485425bb815Sopenharmony_ci
486425bb815Sopenharmony_ci    day = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 31);
487425bb815Sopenharmony_ci    if (ecma_number_is_nan (day))
488425bb815Sopenharmony_ci    {
489425bb815Sopenharmony_ci      return nan;
490425bb815Sopenharmony_ci    }
491425bb815Sopenharmony_ci  }
492425bb815Sopenharmony_ci
493425bb815Sopenharmony_ci  if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ' '))
494425bb815Sopenharmony_ci  {
495425bb815Sopenharmony_ci    return nan;
496425bb815Sopenharmony_ci  }
497425bb815Sopenharmony_ci
498425bb815Sopenharmony_ci  ecma_number_t year = ecma_date_parse_year (&date_str_curr_p, date_str_end_p);
499425bb815Sopenharmony_ci  if (ecma_number_is_nan (year))
500425bb815Sopenharmony_ci  {
501425bb815Sopenharmony_ci    return nan;
502425bb815Sopenharmony_ci  }
503425bb815Sopenharmony_ci
504425bb815Sopenharmony_ci  if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ' '))
505425bb815Sopenharmony_ci  {
506425bb815Sopenharmony_ci    return nan;
507425bb815Sopenharmony_ci  }
508425bb815Sopenharmony_ci
509425bb815Sopenharmony_ci  ecma_number_t hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 24);
510425bb815Sopenharmony_ci  if (ecma_number_is_nan (hours))
511425bb815Sopenharmony_ci  {
512425bb815Sopenharmony_ci    return nan;
513425bb815Sopenharmony_ci  }
514425bb815Sopenharmony_ci
515425bb815Sopenharmony_ci  if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ':'))
516425bb815Sopenharmony_ci  {
517425bb815Sopenharmony_ci    return nan;
518425bb815Sopenharmony_ci  }
519425bb815Sopenharmony_ci
520425bb815Sopenharmony_ci  ecma_number_t minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 59);
521425bb815Sopenharmony_ci  if (ecma_number_is_nan (minutes))
522425bb815Sopenharmony_ci  {
523425bb815Sopenharmony_ci    return nan;
524425bb815Sopenharmony_ci  }
525425bb815Sopenharmony_ci
526425bb815Sopenharmony_ci  if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ':'))
527425bb815Sopenharmony_ci  {
528425bb815Sopenharmony_ci    return nan;
529425bb815Sopenharmony_ci  }
530425bb815Sopenharmony_ci
531425bb815Sopenharmony_ci  ecma_number_t seconds = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 59);
532425bb815Sopenharmony_ci  if (ecma_number_is_nan (seconds))
533425bb815Sopenharmony_ci  {
534425bb815Sopenharmony_ci    return nan;
535425bb815Sopenharmony_ci  }
536425bb815Sopenharmony_ci
537425bb815Sopenharmony_ci  if (hours == 24 && (minutes != 0 || seconds != 0))
538425bb815Sopenharmony_ci  {
539425bb815Sopenharmony_ci    return nan;
540425bb815Sopenharmony_ci  }
541425bb815Sopenharmony_ci
542425bb815Sopenharmony_ci  if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, ' '))
543425bb815Sopenharmony_ci  {
544425bb815Sopenharmony_ci    return nan;
545425bb815Sopenharmony_ci  }
546425bb815Sopenharmony_ci
547425bb815Sopenharmony_ci  if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, 'G'))
548425bb815Sopenharmony_ci  {
549425bb815Sopenharmony_ci    return nan;
550425bb815Sopenharmony_ci  }
551425bb815Sopenharmony_ci
552425bb815Sopenharmony_ci  if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, 'M'))
553425bb815Sopenharmony_ci  {
554425bb815Sopenharmony_ci    return nan;
555425bb815Sopenharmony_ci  }
556425bb815Sopenharmony_ci
557425bb815Sopenharmony_ci  if (!ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, 'T'))
558425bb815Sopenharmony_ci  {
559425bb815Sopenharmony_ci    return nan;
560425bb815Sopenharmony_ci  }
561425bb815Sopenharmony_ci
562425bb815Sopenharmony_ci  ecma_number_t time = ecma_date_make_time (hours, minutes, seconds, 0);
563425bb815Sopenharmony_ci
564425bb815Sopenharmony_ci  if (!is_toUTCString_format)
565425bb815Sopenharmony_ci  {
566425bb815Sopenharmony_ci    bool is_timezone_sign_negative = ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, '-');
567425bb815Sopenharmony_ci    if (!is_timezone_sign_negative && !ecma_date_parse_special_char (&date_str_curr_p, date_str_end_p, '+'))
568425bb815Sopenharmony_ci    {
569425bb815Sopenharmony_ci      return nan;
570425bb815Sopenharmony_ci    }
571425bb815Sopenharmony_ci
572425bb815Sopenharmony_ci    hours = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 24);
573425bb815Sopenharmony_ci    if (ecma_number_is_nan (hours))
574425bb815Sopenharmony_ci    {
575425bb815Sopenharmony_ci      return nan;
576425bb815Sopenharmony_ci    }
577425bb815Sopenharmony_ci    if (hours == 24)
578425bb815Sopenharmony_ci    {
579425bb815Sopenharmony_ci      hours = ECMA_NUMBER_ZERO;
580425bb815Sopenharmony_ci    }
581425bb815Sopenharmony_ci
582425bb815Sopenharmony_ci    minutes = ecma_date_parse_date_chars (&date_str_curr_p, date_str_end_p, 2, 0, 59);
583425bb815Sopenharmony_ci    if (ecma_number_is_nan (minutes))
584425bb815Sopenharmony_ci    {
585425bb815Sopenharmony_ci      return nan;
586425bb815Sopenharmony_ci    }
587425bb815Sopenharmony_ci
588425bb815Sopenharmony_ci    ecma_number_t timezone_offset = ecma_date_make_time (hours, minutes, ECMA_NUMBER_ZERO, ECMA_NUMBER_ZERO);
589425bb815Sopenharmony_ci    time += is_timezone_sign_negative ? timezone_offset : -timezone_offset;
590425bb815Sopenharmony_ci  }
591425bb815Sopenharmony_ci
592425bb815Sopenharmony_ci  if (date_str_curr_p >= date_str_end_p)
593425bb815Sopenharmony_ci  {
594425bb815Sopenharmony_ci    ecma_number_t date = ecma_date_make_day (year, month - 1, day);
595425bb815Sopenharmony_ci    return ecma_date_make_date (date, time);
596425bb815Sopenharmony_ci  }
597425bb815Sopenharmony_ci
598425bb815Sopenharmony_ci  return nan;
599425bb815Sopenharmony_ci} /* ecma_builtin_date_parse_toString_formats */
600425bb815Sopenharmony_ci
601425bb815Sopenharmony_ci/**
602425bb815Sopenharmony_ci * The Date object's 'parse' routine
603425bb815Sopenharmony_ci *
604425bb815Sopenharmony_ci * See also:
605425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.4.2  Date.parse (string)
606425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.15 Date Time String Format
607425bb815Sopenharmony_ci *          ECMA-262 v9, 20.3.4.41 Date.prototype.toString ()
608425bb815Sopenharmony_ci *          ECMA-262 v9, 20.3.4.43 Date.prototype.toUTCString ()
609425bb815Sopenharmony_ci *
610425bb815Sopenharmony_ci * @return ecma value
611425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
612425bb815Sopenharmony_ci */
613425bb815Sopenharmony_cistatic ecma_value_t
614425bb815Sopenharmony_ciecma_builtin_date_parse (ecma_value_t this_arg, /**< this argument */
615425bb815Sopenharmony_ci                         ecma_value_t arg) /**< string */
616425bb815Sopenharmony_ci{
617425bb815Sopenharmony_ci  JERRY_UNUSED (this_arg);
618425bb815Sopenharmony_ci
619425bb815Sopenharmony_ci  /* Date Time String fromat (ECMA-262 v5, 15.9.1.15) */
620425bb815Sopenharmony_ci  ecma_string_t *date_str_p = ecma_op_to_string (arg);
621425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (date_str_p == NULL))
622425bb815Sopenharmony_ci  {
623425bb815Sopenharmony_ci    return ECMA_VALUE_ERROR;
624425bb815Sopenharmony_ci  }
625425bb815Sopenharmony_ci
626425bb815Sopenharmony_ci  ECMA_STRING_TO_UTF8_STRING (date_str_p, date_start_p, date_start_size);
627425bb815Sopenharmony_ci  const lit_utf8_byte_t *date_str_curr_p = date_start_p;
628425bb815Sopenharmony_ci  const lit_utf8_byte_t *date_str_end_p = date_start_p + date_start_size;
629425bb815Sopenharmony_ci
630425bb815Sopenharmony_ci  // try to parse date string as ISO string - ECMA-262 v5, 15.9.1.15
631425bb815Sopenharmony_ci  ecma_number_t ret_value = ecma_builtin_date_parse_ISO_string_format (date_str_curr_p, date_str_end_p);
632425bb815Sopenharmony_ci
633425bb815Sopenharmony_ci  if (ecma_number_is_nan (ret_value))
634425bb815Sopenharmony_ci  {
635425bb815Sopenharmony_ci    // try to parse date string in Date.prototype.toString() or toUTCString() format
636425bb815Sopenharmony_ci    ret_value = ecma_builtin_date_parse_toString_formats (date_str_curr_p, date_str_end_p);
637425bb815Sopenharmony_ci  }
638425bb815Sopenharmony_ci
639425bb815Sopenharmony_ci  ECMA_FINALIZE_UTF8_STRING (date_start_p, date_start_size);
640425bb815Sopenharmony_ci  ecma_deref_ecma_string (date_str_p);
641425bb815Sopenharmony_ci  return ecma_make_number_value (ret_value);
642425bb815Sopenharmony_ci} /* ecma_builtin_date_parse */
643425bb815Sopenharmony_ci
644425bb815Sopenharmony_ci/**
645425bb815Sopenharmony_ci * The Date object's 'UTC' routine
646425bb815Sopenharmony_ci *
647425bb815Sopenharmony_ci * See also:
648425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.4.3
649425bb815Sopenharmony_ci *
650425bb815Sopenharmony_ci * @return ecma value
651425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
652425bb815Sopenharmony_ci */
653425bb815Sopenharmony_cistatic ecma_value_t
654425bb815Sopenharmony_ciecma_builtin_date_utc (ecma_value_t this_arg, /**< this argument */
655425bb815Sopenharmony_ci                       const ecma_value_t args[], /**< arguments list */
656425bb815Sopenharmony_ci                       ecma_length_t args_number) /**< number of arguments */
657425bb815Sopenharmony_ci{
658425bb815Sopenharmony_ci  JERRY_UNUSED (this_arg);
659425bb815Sopenharmony_ci  ecma_value_t ret_value = ECMA_VALUE_EMPTY;
660425bb815Sopenharmony_ci
661425bb815Sopenharmony_ci  if (args_number < 2)
662425bb815Sopenharmony_ci  {
663425bb815Sopenharmony_ci    /* Note:
664425bb815Sopenharmony_ci     *      When the UTC function is called with fewer than two arguments,
665425bb815Sopenharmony_ci     *      the behaviour is implementation-dependent, so just return NaN.
666425bb815Sopenharmony_ci     */
667425bb815Sopenharmony_ci    return ecma_make_number_value (ecma_number_make_nan ());
668425bb815Sopenharmony_ci  }
669425bb815Sopenharmony_ci
670425bb815Sopenharmony_ci  ECMA_TRY_CATCH (time_value, ecma_date_construct_helper (args, args_number), ret_value);
671425bb815Sopenharmony_ci
672425bb815Sopenharmony_ci  ecma_number_t time = ecma_get_number_from_value (time_value);
673425bb815Sopenharmony_ci  ret_value = ecma_make_number_value (ecma_date_time_clip (time));
674425bb815Sopenharmony_ci
675425bb815Sopenharmony_ci  ECMA_FINALIZE (time_value);
676425bb815Sopenharmony_ci
677425bb815Sopenharmony_ci  return ret_value;
678425bb815Sopenharmony_ci} /* ecma_builtin_date_utc */
679425bb815Sopenharmony_ci
680425bb815Sopenharmony_ci/**
681425bb815Sopenharmony_ci * The Date object's 'now' routine
682425bb815Sopenharmony_ci *
683425bb815Sopenharmony_ci * See also:
684425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.4.4
685425bb815Sopenharmony_ci *
686425bb815Sopenharmony_ci * @return ecma value
687425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
688425bb815Sopenharmony_ci */
689425bb815Sopenharmony_cistatic ecma_value_t
690425bb815Sopenharmony_ciecma_builtin_date_now (ecma_value_t this_arg) /**< this argument */
691425bb815Sopenharmony_ci{
692425bb815Sopenharmony_ci  JERRY_UNUSED (this_arg);
693425bb815Sopenharmony_ci  return ecma_make_number_value (floor (DOUBLE_TO_ECMA_NUMBER_T (jerry_port_get_current_time ())));
694425bb815Sopenharmony_ci} /* ecma_builtin_date_now */
695425bb815Sopenharmony_ci
696425bb815Sopenharmony_ci/**
697425bb815Sopenharmony_ci * Handle calling [[Call]] of built-in Date object
698425bb815Sopenharmony_ci *
699425bb815Sopenharmony_ci * See also:
700425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.2.1
701425bb815Sopenharmony_ci *
702425bb815Sopenharmony_ci * @return ecma value
703425bb815Sopenharmony_ci */
704425bb815Sopenharmony_ciecma_value_t
705425bb815Sopenharmony_ciecma_builtin_date_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
706425bb815Sopenharmony_ci                                 ecma_length_t arguments_list_len) /**< number of arguments */
707425bb815Sopenharmony_ci{
708425bb815Sopenharmony_ci  JERRY_UNUSED (arguments_list_p);
709425bb815Sopenharmony_ci  JERRY_UNUSED (arguments_list_len);
710425bb815Sopenharmony_ci  ecma_value_t ret_value = ECMA_VALUE_EMPTY;
711425bb815Sopenharmony_ci
712425bb815Sopenharmony_ci  ECMA_TRY_CATCH (now_val,
713425bb815Sopenharmony_ci                  ecma_builtin_date_now (ECMA_VALUE_UNDEFINED),
714425bb815Sopenharmony_ci                  ret_value);
715425bb815Sopenharmony_ci
716425bb815Sopenharmony_ci  ret_value = ecma_date_value_to_string (ecma_get_number_from_value (now_val));
717425bb815Sopenharmony_ci
718425bb815Sopenharmony_ci  ECMA_FINALIZE (now_val);
719425bb815Sopenharmony_ci
720425bb815Sopenharmony_ci  return ret_value;
721425bb815Sopenharmony_ci} /* ecma_builtin_date_dispatch_call */
722425bb815Sopenharmony_ci
723425bb815Sopenharmony_ci/**
724425bb815Sopenharmony_ci * Handle calling [[Construct]] of built-in Date object
725425bb815Sopenharmony_ci *
726425bb815Sopenharmony_ci * See also:
727425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.3.1
728425bb815Sopenharmony_ci *
729425bb815Sopenharmony_ci * @return ecma value
730425bb815Sopenharmony_ci */
731425bb815Sopenharmony_ciecma_value_t
732425bb815Sopenharmony_ciecma_builtin_date_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
733425bb815Sopenharmony_ci                                      ecma_length_t arguments_list_len) /**< number of arguments */
734425bb815Sopenharmony_ci{
735425bb815Sopenharmony_ci  ecma_value_t ret_value = ECMA_VALUE_EMPTY;
736425bb815Sopenharmony_ci  ecma_number_t prim_value_num = ECMA_NUMBER_ZERO;
737425bb815Sopenharmony_ci
738425bb815Sopenharmony_ci  ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_DATE_PROTOTYPE);
739425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
740425bb815Sopenharmony_ci  if (JERRY_CONTEXT (current_new_target))
741425bb815Sopenharmony_ci  {
742425bb815Sopenharmony_ci    prototype_obj_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_new_target),
743425bb815Sopenharmony_ci                                                              ECMA_BUILTIN_ID_DATE_PROTOTYPE);
744425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (prototype_obj_p == NULL))
745425bb815Sopenharmony_ci    {
746425bb815Sopenharmony_ci      return ECMA_VALUE_ERROR;
747425bb815Sopenharmony_ci    }
748425bb815Sopenharmony_ci  }
749425bb815Sopenharmony_ci#endif /* !(ENABLED (JERRY_ES2015) */
750425bb815Sopenharmony_ci  ecma_object_t *obj_p = ecma_create_object (prototype_obj_p,
751425bb815Sopenharmony_ci                                             sizeof (ecma_extended_object_t),
752425bb815Sopenharmony_ci                                             ECMA_OBJECT_TYPE_CLASS);
753425bb815Sopenharmony_ci
754425bb815Sopenharmony_ci  ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
755425bb815Sopenharmony_ci  ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_UNDEFINED;
756425bb815Sopenharmony_ci
757425bb815Sopenharmony_ci  if (arguments_list_len == 0)
758425bb815Sopenharmony_ci  {
759425bb815Sopenharmony_ci    ECMA_TRY_CATCH (parse_res_value,
760425bb815Sopenharmony_ci                    ecma_builtin_date_now (ecma_make_object_value (obj_p)),
761425bb815Sopenharmony_ci                    ret_value);
762425bb815Sopenharmony_ci
763425bb815Sopenharmony_ci    prim_value_num = ecma_get_number_from_value (parse_res_value);
764425bb815Sopenharmony_ci
765425bb815Sopenharmony_ci    ECMA_FINALIZE (parse_res_value)
766425bb815Sopenharmony_ci  }
767425bb815Sopenharmony_ci  else if (arguments_list_len == 1)
768425bb815Sopenharmony_ci  {
769425bb815Sopenharmony_ci    ECMA_TRY_CATCH (prim_comp_value,
770425bb815Sopenharmony_ci                    ecma_op_to_primitive (arguments_list_p[0], ECMA_PREFERRED_TYPE_NUMBER),
771425bb815Sopenharmony_ci                    ret_value);
772425bb815Sopenharmony_ci
773425bb815Sopenharmony_ci    if (ecma_is_value_string (prim_comp_value))
774425bb815Sopenharmony_ci    {
775425bb815Sopenharmony_ci      ECMA_TRY_CATCH (parse_res_value,
776425bb815Sopenharmony_ci                      ecma_builtin_date_parse (ecma_make_object_value (obj_p), prim_comp_value),
777425bb815Sopenharmony_ci                      ret_value);
778425bb815Sopenharmony_ci
779425bb815Sopenharmony_ci      prim_value_num = ecma_get_number_from_value (parse_res_value);
780425bb815Sopenharmony_ci
781425bb815Sopenharmony_ci      ECMA_FINALIZE (parse_res_value);
782425bb815Sopenharmony_ci    }
783425bb815Sopenharmony_ci    else
784425bb815Sopenharmony_ci    {
785425bb815Sopenharmony_ci      ECMA_TRY_CATCH (prim_value, ecma_op_to_number (arguments_list_p[0]), ret_value);
786425bb815Sopenharmony_ci
787425bb815Sopenharmony_ci      prim_value_num = ecma_date_time_clip (ecma_get_number_from_value (prim_value));
788425bb815Sopenharmony_ci
789425bb815Sopenharmony_ci      ECMA_FINALIZE (prim_value);
790425bb815Sopenharmony_ci    }
791425bb815Sopenharmony_ci
792425bb815Sopenharmony_ci    ECMA_FINALIZE (prim_comp_value);
793425bb815Sopenharmony_ci  }
794425bb815Sopenharmony_ci  else
795425bb815Sopenharmony_ci  {
796425bb815Sopenharmony_ci    ECMA_TRY_CATCH (time_value,
797425bb815Sopenharmony_ci                    ecma_date_construct_helper (arguments_list_p, arguments_list_len),
798425bb815Sopenharmony_ci                    ret_value);
799425bb815Sopenharmony_ci
800425bb815Sopenharmony_ci    ecma_number_t time = ecma_get_number_from_value (time_value);
801425bb815Sopenharmony_ci    prim_value_num = ecma_date_time_clip (ecma_date_utc (time));
802425bb815Sopenharmony_ci
803425bb815Sopenharmony_ci    ECMA_FINALIZE (time_value);
804425bb815Sopenharmony_ci  }
805425bb815Sopenharmony_ci
806425bb815Sopenharmony_ci  if (ecma_is_value_empty (ret_value))
807425bb815Sopenharmony_ci  {
808425bb815Sopenharmony_ci    if (!ecma_number_is_nan (prim_value_num) && ecma_number_is_infinity (prim_value_num))
809425bb815Sopenharmony_ci    {
810425bb815Sopenharmony_ci      prim_value_num = ecma_number_make_nan ();
811425bb815Sopenharmony_ci    }
812425bb815Sopenharmony_ci
813425bb815Sopenharmony_ci    ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_DATE_UL;
814425bb815Sopenharmony_ci
815425bb815Sopenharmony_ci    ecma_number_t *date_num_p = ecma_alloc_number ();
816425bb815Sopenharmony_ci    *date_num_p = prim_value_num;
817425bb815Sopenharmony_ci    ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.class_prop.u.value, date_num_p);
818425bb815Sopenharmony_ci
819425bb815Sopenharmony_ci    ret_value = ecma_make_object_value (obj_p);
820425bb815Sopenharmony_ci  }
821425bb815Sopenharmony_ci  else
822425bb815Sopenharmony_ci  {
823425bb815Sopenharmony_ci    JERRY_ASSERT (ECMA_IS_VALUE_ERROR (ret_value));
824425bb815Sopenharmony_ci    ecma_deref_object (obj_p);
825425bb815Sopenharmony_ci  }
826425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
827425bb815Sopenharmony_ci  if (JERRY_CONTEXT (current_new_target))
828425bb815Sopenharmony_ci  {
829425bb815Sopenharmony_ci    ecma_deref_object (prototype_obj_p);
830425bb815Sopenharmony_ci  }
831425bb815Sopenharmony_ci#endif /* !(ENABLED (JERRY_ES2015) */
832425bb815Sopenharmony_ci  return ret_value;
833425bb815Sopenharmony_ci} /* ecma_builtin_date_dispatch_construct */
834425bb815Sopenharmony_ci
835425bb815Sopenharmony_ci/**
836425bb815Sopenharmony_ci * @}
837425bb815Sopenharmony_ci * @}
838425bb815Sopenharmony_ci * @}
839425bb815Sopenharmony_ci */
840425bb815Sopenharmony_ci
841425bb815Sopenharmony_ci#undef BREAK_IF_FALSE
842425bb815Sopenharmony_ci#undef BREAK_IF_NAN
843425bb815Sopenharmony_ci
844425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_DATE) */
845