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 "ecma-alloc.h"
19425bb815Sopenharmony_ci#include "ecma-builtin-helpers.h"
20425bb815Sopenharmony_ci#include "ecma-exceptions.h"
21425bb815Sopenharmony_ci#include "ecma-globals.h"
22425bb815Sopenharmony_ci#include "ecma-helpers.h"
23425bb815Sopenharmony_ci#include "ecma-objects.h"
24425bb815Sopenharmony_ci#include "ecma-try-catch-macro.h"
25425bb815Sopenharmony_ci#include "lit-char-helpers.h"
26425bb815Sopenharmony_ci
27425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_DATE)
28425bb815Sopenharmony_ci
29425bb815Sopenharmony_ci/** \addtogroup ecma ECMA
30425bb815Sopenharmony_ci * @{
31425bb815Sopenharmony_ci *
32425bb815Sopenharmony_ci * \addtogroup ecmabuiltinhelpers ECMA builtin helper operations
33425bb815Sopenharmony_ci * @{
34425bb815Sopenharmony_ci */
35425bb815Sopenharmony_ci
36425bb815Sopenharmony_ciconst char day_names_p[7][3] =
37425bb815Sopenharmony_ci{
38425bb815Sopenharmony_ci  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
39425bb815Sopenharmony_ci};
40425bb815Sopenharmony_ci
41425bb815Sopenharmony_ciconst char month_names_p[12][3] =
42425bb815Sopenharmony_ci{
43425bb815Sopenharmony_ci  "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
44425bb815Sopenharmony_ci};
45425bb815Sopenharmony_ci
46425bb815Sopenharmony_ci/**
47425bb815Sopenharmony_ci * Helper function to get day number from time value.
48425bb815Sopenharmony_ci *
49425bb815Sopenharmony_ci * See also:
50425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.2
51425bb815Sopenharmony_ci *
52425bb815Sopenharmony_ci * @return time value for day number
53425bb815Sopenharmony_ci */
54425bb815Sopenharmony_ciextern inline ecma_number_t JERRY_ATTR_ALWAYS_INLINE
55425bb815Sopenharmony_ciecma_date_day (ecma_number_t time) /**< time value */
56425bb815Sopenharmony_ci{
57425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (time));
58425bb815Sopenharmony_ci
59425bb815Sopenharmony_ci  return (ecma_number_t) floor (time / ECMA_DATE_MS_PER_DAY);
60425bb815Sopenharmony_ci} /* ecma_date_day */
61425bb815Sopenharmony_ci
62425bb815Sopenharmony_ci/**
63425bb815Sopenharmony_ci * Helper function to get time within day from time value.
64425bb815Sopenharmony_ci *
65425bb815Sopenharmony_ci * See also:
66425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.2
67425bb815Sopenharmony_ci *
68425bb815Sopenharmony_ci * @return time value within the day
69425bb815Sopenharmony_ci */
70425bb815Sopenharmony_ciextern inline ecma_number_t JERRY_ATTR_ALWAYS_INLINE
71425bb815Sopenharmony_ciecma_date_time_within_day (ecma_number_t time) /**< time value */
72425bb815Sopenharmony_ci{
73425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (time));
74425bb815Sopenharmony_ci
75425bb815Sopenharmony_ci  ecma_number_t modulo = fmod (time, ECMA_DATE_MS_PER_DAY);
76425bb815Sopenharmony_ci  if (modulo < 0)
77425bb815Sopenharmony_ci  {
78425bb815Sopenharmony_ci    modulo += ECMA_DATE_MS_PER_DAY;
79425bb815Sopenharmony_ci  }
80425bb815Sopenharmony_ci
81425bb815Sopenharmony_ci  return modulo;
82425bb815Sopenharmony_ci} /* ecma_date_time_within_day */
83425bb815Sopenharmony_ci
84425bb815Sopenharmony_ci/**
85425bb815Sopenharmony_ci * Helper function to get the day number of the first day of a year.
86425bb815Sopenharmony_ci *
87425bb815Sopenharmony_ci * See also:
88425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.3
89425bb815Sopenharmony_ci *
90425bb815Sopenharmony_ci * @return day number of the first day of a year
91425bb815Sopenharmony_ci */
92425bb815Sopenharmony_cistatic ecma_number_t
93425bb815Sopenharmony_ciecma_date_day_from_year (ecma_number_t year) /**< year value */
94425bb815Sopenharmony_ci{
95425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (year));
96425bb815Sopenharmony_ci
97425bb815Sopenharmony_ci  return (ecma_number_t) (365 * (year - 1970)
98425bb815Sopenharmony_ci                          + floor ((year - 1969) / 4)
99425bb815Sopenharmony_ci                          - floor ((year - 1901) / 100)
100425bb815Sopenharmony_ci                          + floor ((year - 1601) / 400));
101425bb815Sopenharmony_ci} /* ecma_date_day_from_year */
102425bb815Sopenharmony_ci
103425bb815Sopenharmony_ci/**
104425bb815Sopenharmony_ci * Helper function to get the time value of the start of a year.
105425bb815Sopenharmony_ci *
106425bb815Sopenharmony_ci * See also:
107425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.3
108425bb815Sopenharmony_ci *
109425bb815Sopenharmony_ci * @return  time value of the start of a year
110425bb815Sopenharmony_ci */
111425bb815Sopenharmony_cistatic inline ecma_number_t JERRY_ATTR_ALWAYS_INLINE
112425bb815Sopenharmony_ciecma_date_time_from_year (ecma_number_t year) /**< year value */
113425bb815Sopenharmony_ci{
114425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (year));
115425bb815Sopenharmony_ci
116425bb815Sopenharmony_ci  return ECMA_DATE_MS_PER_DAY * ecma_date_day_from_year (year);
117425bb815Sopenharmony_ci} /* ecma_date_time_from_year */
118425bb815Sopenharmony_ci
119425bb815Sopenharmony_ci/**
120425bb815Sopenharmony_ci * Helper function to determine a year value from the time value.
121425bb815Sopenharmony_ci *
122425bb815Sopenharmony_ci * See also:
123425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.3
124425bb815Sopenharmony_ci *
125425bb815Sopenharmony_ci * @return year value
126425bb815Sopenharmony_ci */
127425bb815Sopenharmony_ciecma_number_t
128425bb815Sopenharmony_ciecma_date_year_from_time (ecma_number_t time) /**< time value */
129425bb815Sopenharmony_ci{
130425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (time));
131425bb815Sopenharmony_ci
132425bb815Sopenharmony_ci  /* ECMA-262 v5, 15.9.1.1 define the largest year that is
133425bb815Sopenharmony_ci   * representable (285616) forward from 01 January, 1970 UTC.
134425bb815Sopenharmony_ci   */
135425bb815Sopenharmony_ci  ecma_number_t year = (ecma_number_t) (1970 + 285616);
136425bb815Sopenharmony_ci  ecma_number_t lower_year_boundary = (ecma_number_t) (1970 - 285616);
137425bb815Sopenharmony_ci
138425bb815Sopenharmony_ci  if (ecma_date_time_from_year (year) < time || ecma_date_time_from_year (lower_year_boundary) > time)
139425bb815Sopenharmony_ci  {
140425bb815Sopenharmony_ci    return ecma_number_make_nan ();
141425bb815Sopenharmony_ci  }
142425bb815Sopenharmony_ci
143425bb815Sopenharmony_ci  while (ecma_date_time_from_year (year) > time)
144425bb815Sopenharmony_ci  {
145425bb815Sopenharmony_ci    ecma_number_t year_boundary = (ecma_number_t) floor (lower_year_boundary + (year - lower_year_boundary) / 2);
146425bb815Sopenharmony_ci    if (ecma_date_time_from_year (year_boundary) > time)
147425bb815Sopenharmony_ci    {
148425bb815Sopenharmony_ci      year = year_boundary;
149425bb815Sopenharmony_ci    }
150425bb815Sopenharmony_ci    else
151425bb815Sopenharmony_ci    {
152425bb815Sopenharmony_ci      lower_year_boundary = year_boundary;
153425bb815Sopenharmony_ci    }
154425bb815Sopenharmony_ci
155425bb815Sopenharmony_ci    year--;
156425bb815Sopenharmony_ci  }
157425bb815Sopenharmony_ci
158425bb815Sopenharmony_ci  return year;
159425bb815Sopenharmony_ci} /* ecma_date_year_from_time */
160425bb815Sopenharmony_ci
161425bb815Sopenharmony_ci/**
162425bb815Sopenharmony_ci * Helper function to decide if time value is in a leap-year.
163425bb815Sopenharmony_ci *
164425bb815Sopenharmony_ci * See also:
165425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.3
166425bb815Sopenharmony_ci *
167425bb815Sopenharmony_ci * @return 1 if time within a leap year
168425bb815Sopenharmony_ci *         0 otherwise
169425bb815Sopenharmony_ci */
170425bb815Sopenharmony_cistatic int
171425bb815Sopenharmony_ciecma_date_in_leap_year (ecma_number_t year) /**< time value */
172425bb815Sopenharmony_ci{
173425bb815Sopenharmony_ci  int mod_400 = (int) fmod (floor (year), 400);
174425bb815Sopenharmony_ci
175425bb815Sopenharmony_ci  JERRY_ASSERT (mod_400 >= -399 && mod_400 <= 399);
176425bb815Sopenharmony_ci
177425bb815Sopenharmony_ci  if ((mod_400 % 4) != 0)
178425bb815Sopenharmony_ci  {
179425bb815Sopenharmony_ci    return 0;
180425bb815Sopenharmony_ci  }
181425bb815Sopenharmony_ci
182425bb815Sopenharmony_ci  if ((mod_400 % 100) != 0)
183425bb815Sopenharmony_ci  {
184425bb815Sopenharmony_ci    return 1;
185425bb815Sopenharmony_ci  }
186425bb815Sopenharmony_ci
187425bb815Sopenharmony_ci  if (mod_400 != 0)
188425bb815Sopenharmony_ci  {
189425bb815Sopenharmony_ci    return 0;
190425bb815Sopenharmony_ci  }
191425bb815Sopenharmony_ci
192425bb815Sopenharmony_ci  return 1;
193425bb815Sopenharmony_ci} /* ecma_date_in_leap_year */
194425bb815Sopenharmony_ci
195425bb815Sopenharmony_ci/**
196425bb815Sopenharmony_ci * End day for the first 11 months.
197425bb815Sopenharmony_ci */
198425bb815Sopenharmony_cistatic const int16_t ecma_date_month_end_day[10] =
199425bb815Sopenharmony_ci{
200425bb815Sopenharmony_ci  58, 89, 119, 150, 180, 211, 242, 272, 303, 333
201425bb815Sopenharmony_ci};
202425bb815Sopenharmony_ci
203425bb815Sopenharmony_ci/**
204425bb815Sopenharmony_ci * Helper function to get month from time value.
205425bb815Sopenharmony_ci *
206425bb815Sopenharmony_ci * See also:
207425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.4
208425bb815Sopenharmony_ci *
209425bb815Sopenharmony_ci * @return month number
210425bb815Sopenharmony_ci */
211425bb815Sopenharmony_ciecma_number_t
212425bb815Sopenharmony_ciecma_date_month_from_time (ecma_number_t time) /**< time value */
213425bb815Sopenharmony_ci{
214425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (time));
215425bb815Sopenharmony_ci
216425bb815Sopenharmony_ci  ecma_number_t year = ecma_date_year_from_time (time);
217425bb815Sopenharmony_ci
218425bb815Sopenharmony_ci  if (ecma_number_is_nan (year))
219425bb815Sopenharmony_ci  {
220425bb815Sopenharmony_ci    return ecma_number_make_nan ();
221425bb815Sopenharmony_ci  }
222425bb815Sopenharmony_ci
223425bb815Sopenharmony_ci  int day_within_year = (int) (ecma_date_day (time) - ecma_date_day_from_year (year));
224425bb815Sopenharmony_ci
225425bb815Sopenharmony_ci  JERRY_ASSERT (day_within_year >= 0);
226425bb815Sopenharmony_ci
227425bb815Sopenharmony_ci  if (day_within_year <= 30)
228425bb815Sopenharmony_ci  {
229425bb815Sopenharmony_ci    return 0;
230425bb815Sopenharmony_ci  }
231425bb815Sopenharmony_ci
232425bb815Sopenharmony_ci  day_within_year -= ecma_date_in_leap_year (year);
233425bb815Sopenharmony_ci
234425bb815Sopenharmony_ci  JERRY_ASSERT (day_within_year < 365);
235425bb815Sopenharmony_ci
236425bb815Sopenharmony_ci  for (int i = 0; i < 10; i++)
237425bb815Sopenharmony_ci  {
238425bb815Sopenharmony_ci    if (day_within_year <= ecma_date_month_end_day[i])
239425bb815Sopenharmony_ci    {
240425bb815Sopenharmony_ci      return i + 1;
241425bb815Sopenharmony_ci    }
242425bb815Sopenharmony_ci  }
243425bb815Sopenharmony_ci
244425bb815Sopenharmony_ci  return 11;
245425bb815Sopenharmony_ci} /* ecma_date_month_from_time */
246425bb815Sopenharmony_ci
247425bb815Sopenharmony_ci/**
248425bb815Sopenharmony_ci * Helper function to get date number from time value.
249425bb815Sopenharmony_ci *
250425bb815Sopenharmony_ci * See also:
251425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.5
252425bb815Sopenharmony_ci *
253425bb815Sopenharmony_ci * @return date number
254425bb815Sopenharmony_ci */
255425bb815Sopenharmony_ciecma_number_t
256425bb815Sopenharmony_ciecma_date_date_from_time (ecma_number_t time) /**< time value */
257425bb815Sopenharmony_ci{
258425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (time));
259425bb815Sopenharmony_ci
260425bb815Sopenharmony_ci  ecma_number_t year = ecma_date_year_from_time (time);
261425bb815Sopenharmony_ci
262425bb815Sopenharmony_ci  if (ecma_number_is_nan (year))
263425bb815Sopenharmony_ci  {
264425bb815Sopenharmony_ci    return ecma_number_make_nan ();
265425bb815Sopenharmony_ci  }
266425bb815Sopenharmony_ci
267425bb815Sopenharmony_ci  int day_within_year = (int) (ecma_date_day (time) - ecma_date_day_from_year (year));
268425bb815Sopenharmony_ci
269425bb815Sopenharmony_ci  JERRY_ASSERT (day_within_year >= 0);
270425bb815Sopenharmony_ci
271425bb815Sopenharmony_ci  if (day_within_year <= 30)
272425bb815Sopenharmony_ci  {
273425bb815Sopenharmony_ci    return day_within_year + 1;
274425bb815Sopenharmony_ci  }
275425bb815Sopenharmony_ci
276425bb815Sopenharmony_ci  int leap_year = ecma_date_in_leap_year (year);
277425bb815Sopenharmony_ci
278425bb815Sopenharmony_ci  if (day_within_year <= 58 + leap_year)
279425bb815Sopenharmony_ci  {
280425bb815Sopenharmony_ci    return day_within_year - 30;
281425bb815Sopenharmony_ci  }
282425bb815Sopenharmony_ci
283425bb815Sopenharmony_ci  day_within_year -= leap_year;
284425bb815Sopenharmony_ci
285425bb815Sopenharmony_ci  JERRY_ASSERT (day_within_year < 365);
286425bb815Sopenharmony_ci
287425bb815Sopenharmony_ci  for (int i = 1; i < 10; i++)
288425bb815Sopenharmony_ci  {
289425bb815Sopenharmony_ci    if (day_within_year <= ecma_date_month_end_day[i])
290425bb815Sopenharmony_ci    {
291425bb815Sopenharmony_ci      return day_within_year - ecma_date_month_end_day[i - 1];
292425bb815Sopenharmony_ci    }
293425bb815Sopenharmony_ci  }
294425bb815Sopenharmony_ci
295425bb815Sopenharmony_ci  return day_within_year - 333;
296425bb815Sopenharmony_ci} /* ecma_date_date_from_time */
297425bb815Sopenharmony_ci
298425bb815Sopenharmony_ci/**
299425bb815Sopenharmony_ci * Helper function to get weekday from time value.
300425bb815Sopenharmony_ci *
301425bb815Sopenharmony_ci * See also:
302425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.6
303425bb815Sopenharmony_ci *
304425bb815Sopenharmony_ci * Used by:
305425bb815Sopenharmony_ci *         - The Date.prototype.getDay routine. (Generated.)
306425bb815Sopenharmony_ci *         - The Date.prototype.getUTCDay routine. (Generated.)
307425bb815Sopenharmony_ci *
308425bb815Sopenharmony_ci * @return  weekday number
309425bb815Sopenharmony_ci */
310425bb815Sopenharmony_ciecma_number_t
311425bb815Sopenharmony_ciecma_date_week_day (ecma_number_t time) /**< time value */
312425bb815Sopenharmony_ci{
313425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (time));
314425bb815Sopenharmony_ci
315425bb815Sopenharmony_ci  ecma_number_t week_day = (ecma_number_t) fmod ((ecma_date_day (time) + 4), 7);
316425bb815Sopenharmony_ci
317425bb815Sopenharmony_ci  return (week_day < 0) ? (7 + week_day) : week_day;
318425bb815Sopenharmony_ci} /* ecma_date_week_day */
319425bb815Sopenharmony_ci
320425bb815Sopenharmony_ci/**
321425bb815Sopenharmony_ci * Helper function to get the local time zone offset at a given UTC timestamp.
322425bb815Sopenharmony_ci * You can add this number to the given UTC timestamp to get local time.
323425bb815Sopenharmony_ci *
324425bb815Sopenharmony_ci * See also:
325425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.9
326425bb815Sopenharmony_ci *
327425bb815Sopenharmony_ci * @return local time zone adjustment
328425bb815Sopenharmony_ci */
329425bb815Sopenharmony_ciinline ecma_number_t JERRY_ATTR_ALWAYS_INLINE
330425bb815Sopenharmony_ciecma_date_local_time_zone_adjustment (ecma_number_t time) /**< time value */
331425bb815Sopenharmony_ci{
332425bb815Sopenharmony_ci  return jerry_port_get_local_time_zone_adjustment (time, true);
333425bb815Sopenharmony_ci} /* ecma_date_local_time_zone_adjustment */
334425bb815Sopenharmony_ci
335425bb815Sopenharmony_ci/**
336425bb815Sopenharmony_ci * Helper function to get UTC time from local time.
337425bb815Sopenharmony_ci *
338425bb815Sopenharmony_ci * See also:
339425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.9
340425bb815Sopenharmony_ci *
341425bb815Sopenharmony_ci * @return UTC time
342425bb815Sopenharmony_ci */
343425bb815Sopenharmony_ciecma_number_t
344425bb815Sopenharmony_ciecma_date_utc (ecma_number_t time) /**< time value */
345425bb815Sopenharmony_ci{
346425bb815Sopenharmony_ci  return time - jerry_port_get_local_time_zone_adjustment (time, false);
347425bb815Sopenharmony_ci} /* ecma_date_utc */
348425bb815Sopenharmony_ci
349425bb815Sopenharmony_ci/**
350425bb815Sopenharmony_ci * Helper function to get hour from time value.
351425bb815Sopenharmony_ci *
352425bb815Sopenharmony_ci * See also:
353425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.10
354425bb815Sopenharmony_ci *
355425bb815Sopenharmony_ci * @return hour value
356425bb815Sopenharmony_ci */
357425bb815Sopenharmony_ciecma_number_t
358425bb815Sopenharmony_ciecma_date_hour_from_time (ecma_number_t time) /**< time value */
359425bb815Sopenharmony_ci{
360425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (time));
361425bb815Sopenharmony_ci
362425bb815Sopenharmony_ci  ecma_number_t hour = (ecma_number_t) fmod (floor (time / ECMA_DATE_MS_PER_HOUR),
363425bb815Sopenharmony_ci                                             ECMA_DATE_HOURS_PER_DAY);
364425bb815Sopenharmony_ci  return (hour < 0) ? ECMA_DATE_HOURS_PER_DAY + hour : hour;
365425bb815Sopenharmony_ci} /* ecma_date_hour_from_time */
366425bb815Sopenharmony_ci
367425bb815Sopenharmony_ci/**
368425bb815Sopenharmony_ci * Helper function to get minute from time value.
369425bb815Sopenharmony_ci *
370425bb815Sopenharmony_ci * See also:
371425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.10
372425bb815Sopenharmony_ci *
373425bb815Sopenharmony_ci * @return minute value
374425bb815Sopenharmony_ci */
375425bb815Sopenharmony_ciecma_number_t
376425bb815Sopenharmony_ciecma_date_min_from_time (ecma_number_t time) /**< time value */
377425bb815Sopenharmony_ci{
378425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (time));
379425bb815Sopenharmony_ci
380425bb815Sopenharmony_ci  ecma_number_t min = (ecma_number_t) fmod (floor (time / ECMA_DATE_MS_PER_MINUTE),
381425bb815Sopenharmony_ci                                            ECMA_DATE_MINUTES_PER_HOUR);
382425bb815Sopenharmony_ci  return (min < 0) ? ECMA_DATE_MINUTES_PER_HOUR + min : min;
383425bb815Sopenharmony_ci} /* ecma_date_min_from_time */
384425bb815Sopenharmony_ci
385425bb815Sopenharmony_ci/**
386425bb815Sopenharmony_ci * Helper function to get second from time value.
387425bb815Sopenharmony_ci *
388425bb815Sopenharmony_ci * See also:
389425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.10
390425bb815Sopenharmony_ci *
391425bb815Sopenharmony_ci * @return second value
392425bb815Sopenharmony_ci */
393425bb815Sopenharmony_ciecma_number_t
394425bb815Sopenharmony_ciecma_date_sec_from_time (ecma_number_t time) /**< time value */
395425bb815Sopenharmony_ci{
396425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (time));
397425bb815Sopenharmony_ci
398425bb815Sopenharmony_ci  ecma_number_t sec = (ecma_number_t) fmod (floor (time / ECMA_DATE_MS_PER_SECOND),
399425bb815Sopenharmony_ci                                            ECMA_DATE_SECONDS_PER_MINUTE);
400425bb815Sopenharmony_ci  return (sec < 0) ? ECMA_DATE_SECONDS_PER_MINUTE + sec : sec;
401425bb815Sopenharmony_ci} /* ecma_date_sec_from_time */
402425bb815Sopenharmony_ci
403425bb815Sopenharmony_ci/**
404425bb815Sopenharmony_ci * Helper function to get millisecond from time value.
405425bb815Sopenharmony_ci *
406425bb815Sopenharmony_ci * See also:
407425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.10
408425bb815Sopenharmony_ci *
409425bb815Sopenharmony_ci * @return millisecond value
410425bb815Sopenharmony_ci */
411425bb815Sopenharmony_ciecma_number_t
412425bb815Sopenharmony_ciecma_date_ms_from_time (ecma_number_t time) /**< time value */
413425bb815Sopenharmony_ci{
414425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (time));
415425bb815Sopenharmony_ci
416425bb815Sopenharmony_ci  ecma_number_t milli = (ecma_number_t) fmod (time, ECMA_DATE_MS_PER_SECOND);
417425bb815Sopenharmony_ci  return (milli < 0) ? ECMA_DATE_MS_PER_SECOND + milli : milli;
418425bb815Sopenharmony_ci} /* ecma_date_ms_from_time */
419425bb815Sopenharmony_ci
420425bb815Sopenharmony_ci/**
421425bb815Sopenharmony_ci * Helper function to make time value from hour, min, sec and ms.
422425bb815Sopenharmony_ci *
423425bb815Sopenharmony_ci * See also:
424425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.11
425425bb815Sopenharmony_ci *
426425bb815Sopenharmony_ci * @return time value
427425bb815Sopenharmony_ci */
428425bb815Sopenharmony_ciecma_number_t
429425bb815Sopenharmony_ciecma_date_make_time (ecma_number_t hour, /**< hour value */
430425bb815Sopenharmony_ci                     ecma_number_t min, /**< minute value */
431425bb815Sopenharmony_ci                     ecma_number_t sec, /**< second value */
432425bb815Sopenharmony_ci                     ecma_number_t ms) /**< millisecond value */
433425bb815Sopenharmony_ci{
434425bb815Sopenharmony_ci  if (ecma_number_is_nan (hour)
435425bb815Sopenharmony_ci      || ecma_number_is_nan (min)
436425bb815Sopenharmony_ci      || ecma_number_is_nan (sec)
437425bb815Sopenharmony_ci      || ecma_number_is_nan (ms)
438425bb815Sopenharmony_ci      || ecma_number_is_infinity (hour)
439425bb815Sopenharmony_ci      || ecma_number_is_infinity (min)
440425bb815Sopenharmony_ci      || ecma_number_is_infinity (sec)
441425bb815Sopenharmony_ci      || ecma_number_is_infinity (ms))
442425bb815Sopenharmony_ci  {
443425bb815Sopenharmony_ci    return ecma_number_make_nan ();
444425bb815Sopenharmony_ci  }
445425bb815Sopenharmony_ci
446425bb815Sopenharmony_ci  /* Replaced toInteger to ecma_number_trunc because it does the same thing. */
447425bb815Sopenharmony_ci  ecma_number_t h = ecma_number_trunc (hour);
448425bb815Sopenharmony_ci  ecma_number_t m = ecma_number_trunc (min);
449425bb815Sopenharmony_ci  ecma_number_t s = ecma_number_trunc (sec);
450425bb815Sopenharmony_ci  ecma_number_t milli = ecma_number_trunc (ms);
451425bb815Sopenharmony_ci
452425bb815Sopenharmony_ci  return (h * ECMA_DATE_MS_PER_HOUR
453425bb815Sopenharmony_ci          + m * ECMA_DATE_MS_PER_MINUTE
454425bb815Sopenharmony_ci          + s * ECMA_DATE_MS_PER_SECOND
455425bb815Sopenharmony_ci          + milli);
456425bb815Sopenharmony_ci} /* ecma_date_make_time */
457425bb815Sopenharmony_ci
458425bb815Sopenharmony_ci/**
459425bb815Sopenharmony_ci * Helper function to make day value from year, month and date.
460425bb815Sopenharmony_ci *
461425bb815Sopenharmony_ci * See also:
462425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.12
463425bb815Sopenharmony_ci *
464425bb815Sopenharmony_ci * @return day value
465425bb815Sopenharmony_ci */
466425bb815Sopenharmony_ciecma_number_t
467425bb815Sopenharmony_ciecma_date_make_day (ecma_number_t year, /**< year value */
468425bb815Sopenharmony_ci                    ecma_number_t month, /**< month value */
469425bb815Sopenharmony_ci                    ecma_number_t date) /**< date value */
470425bb815Sopenharmony_ci{
471425bb815Sopenharmony_ci  /* 1. */
472425bb815Sopenharmony_ci  if (ecma_number_is_nan (year)
473425bb815Sopenharmony_ci      || ecma_number_is_nan (month)
474425bb815Sopenharmony_ci      || ecma_number_is_nan (date)
475425bb815Sopenharmony_ci      || ecma_number_is_infinity (year)
476425bb815Sopenharmony_ci      || ecma_number_is_infinity (month)
477425bb815Sopenharmony_ci      || ecma_number_is_infinity (date))
478425bb815Sopenharmony_ci  {
479425bb815Sopenharmony_ci    return ecma_number_make_nan ();
480425bb815Sopenharmony_ci  }
481425bb815Sopenharmony_ci
482425bb815Sopenharmony_ci  /* 2., 3., 4. */
483425bb815Sopenharmony_ci  ecma_number_t y = ecma_number_trunc (year);
484425bb815Sopenharmony_ci  ecma_number_t m = ecma_number_trunc (month);
485425bb815Sopenharmony_ci  ecma_number_t dt = ecma_number_trunc (date);
486425bb815Sopenharmony_ci  /* 5. */
487425bb815Sopenharmony_ci  ecma_number_t ym = y + (ecma_number_t) floor (m / 12);
488425bb815Sopenharmony_ci  /* 6. */
489425bb815Sopenharmony_ci  ecma_number_t mn = (ecma_number_t) fmod (m, 12);
490425bb815Sopenharmony_ci  mn = (mn < 0) ? 12 + mn : mn;
491425bb815Sopenharmony_ci
492425bb815Sopenharmony_ci  /* 7. */
493425bb815Sopenharmony_ci  ecma_number_t time = ecma_date_time_from_year (ym);
494425bb815Sopenharmony_ci
495425bb815Sopenharmony_ci  /**
496425bb815Sopenharmony_ci   * The algorithm below searches the following date: ym-mn-1
497425bb815Sopenharmony_ci   * To find this time it starts from the beginning of the year (ym)
498425bb815Sopenharmony_ci   * then find the first day of the month.
499425bb815Sopenharmony_ci   */
500425bb815Sopenharmony_ci  if (!ecma_number_is_nan (time)
501425bb815Sopenharmony_ci      && ecma_date_year_from_time (time) == ym)
502425bb815Sopenharmony_ci  {
503425bb815Sopenharmony_ci    /* Get the month */
504425bb815Sopenharmony_ci    time += 31 * mn * ECMA_DATE_MS_PER_DAY;
505425bb815Sopenharmony_ci
506425bb815Sopenharmony_ci    /* Get the month's first day */
507425bb815Sopenharmony_ci    time += ((ecma_number_t) 1.0 - ecma_date_date_from_time (time)) * ECMA_DATE_MS_PER_DAY;
508425bb815Sopenharmony_ci
509425bb815Sopenharmony_ci    if (!ecma_number_is_nan (time)
510425bb815Sopenharmony_ci        && ecma_date_month_from_time (time) == mn
511425bb815Sopenharmony_ci        && ecma_date_date_from_time (time) == 1)
512425bb815Sopenharmony_ci    {
513425bb815Sopenharmony_ci      /* 8. */
514425bb815Sopenharmony_ci      return ecma_date_day (time) + dt - ((ecma_number_t) 1.0);
515425bb815Sopenharmony_ci    }
516425bb815Sopenharmony_ci  }
517425bb815Sopenharmony_ci
518425bb815Sopenharmony_ci  return ecma_number_make_nan ();
519425bb815Sopenharmony_ci} /* ecma_date_make_day */
520425bb815Sopenharmony_ci
521425bb815Sopenharmony_ci/**
522425bb815Sopenharmony_ci * Helper function to make date value from day and time.
523425bb815Sopenharmony_ci *
524425bb815Sopenharmony_ci * See also:
525425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.13
526425bb815Sopenharmony_ci *
527425bb815Sopenharmony_ci * @return date value
528425bb815Sopenharmony_ci */
529425bb815Sopenharmony_ciecma_number_t
530425bb815Sopenharmony_ciecma_date_make_date (ecma_number_t day, /**< day value */
531425bb815Sopenharmony_ci                     ecma_number_t time) /**< time value */
532425bb815Sopenharmony_ci{
533425bb815Sopenharmony_ci  if (ecma_number_is_nan (day)
534425bb815Sopenharmony_ci      || ecma_number_is_nan (time))
535425bb815Sopenharmony_ci  {
536425bb815Sopenharmony_ci    return ecma_number_make_nan ();
537425bb815Sopenharmony_ci  }
538425bb815Sopenharmony_ci
539425bb815Sopenharmony_ci  ecma_number_t result = day * ECMA_DATE_MS_PER_DAY + time;
540425bb815Sopenharmony_ci
541425bb815Sopenharmony_ci  if (ecma_number_is_infinity (result))
542425bb815Sopenharmony_ci  {
543425bb815Sopenharmony_ci    return ecma_number_make_nan ();
544425bb815Sopenharmony_ci  }
545425bb815Sopenharmony_ci
546425bb815Sopenharmony_ci  return result;
547425bb815Sopenharmony_ci} /* ecma_date_make_date */
548425bb815Sopenharmony_ci
549425bb815Sopenharmony_ci/**
550425bb815Sopenharmony_ci * Helper function to calculate number of milliseconds from time value.
551425bb815Sopenharmony_ci *
552425bb815Sopenharmony_ci * See also:
553425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.1.14
554425bb815Sopenharmony_ci *
555425bb815Sopenharmony_ci * @return number of milliseconds
556425bb815Sopenharmony_ci */
557425bb815Sopenharmony_ciecma_number_t
558425bb815Sopenharmony_ciecma_date_time_clip (ecma_number_t time) /**< time value */
559425bb815Sopenharmony_ci{
560425bb815Sopenharmony_ci  if (ecma_number_is_nan (time)
561425bb815Sopenharmony_ci      || ecma_number_is_infinity (time)
562425bb815Sopenharmony_ci      || fabs (time) > ECMA_DATE_MAX_VALUE)
563425bb815Sopenharmony_ci  {
564425bb815Sopenharmony_ci    return ecma_number_make_nan ();
565425bb815Sopenharmony_ci  }
566425bb815Sopenharmony_ci
567425bb815Sopenharmony_ci  return ecma_number_trunc (time);
568425bb815Sopenharmony_ci} /* ecma_date_time_clip */
569425bb815Sopenharmony_ci
570425bb815Sopenharmony_ci/**
571425bb815Sopenharmony_ci * Helper function to calculate timezone offset.
572425bb815Sopenharmony_ci *
573425bb815Sopenharmony_ci * See also:
574425bb815Sopenharmony_ci *          ECMA-262 v5, 15.9.5.26
575425bb815Sopenharmony_ci *
576425bb815Sopenharmony_ci * @return timezone offset
577425bb815Sopenharmony_ci */
578425bb815Sopenharmony_ciinline ecma_number_t JERRY_ATTR_ALWAYS_INLINE
579425bb815Sopenharmony_ciecma_date_timezone_offset (ecma_number_t time) /**< time value */
580425bb815Sopenharmony_ci{
581425bb815Sopenharmony_ci  JERRY_ASSERT (!ecma_number_is_nan (time));
582425bb815Sopenharmony_ci
583425bb815Sopenharmony_ci  return (-ecma_date_local_time_zone_adjustment (time)) / ECMA_DATE_MS_PER_MINUTE;
584425bb815Sopenharmony_ci} /* ecma_date_timezone_offset */
585425bb815Sopenharmony_ci
586425bb815Sopenharmony_ci/**
587425bb815Sopenharmony_ci * Common function to convert date to string.
588425bb815Sopenharmony_ci *
589425bb815Sopenharmony_ci * @return ecma value
590425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
591425bb815Sopenharmony_ci */
592425bb815Sopenharmony_cistatic ecma_value_t
593425bb815Sopenharmony_ciecma_date_to_string_format (ecma_number_t datetime_number, /**< datetime */
594425bb815Sopenharmony_ci                            const char *format_p) /**< format buffer */
595425bb815Sopenharmony_ci{
596425bb815Sopenharmony_ci  const uint32_t date_buffer_length = 37;
597425bb815Sopenharmony_ci  JERRY_VLA (lit_utf8_byte_t, date_buffer, date_buffer_length);
598425bb815Sopenharmony_ci
599425bb815Sopenharmony_ci  lit_utf8_byte_t *dest_p = date_buffer;
600425bb815Sopenharmony_ci
601425bb815Sopenharmony_ci  while (*format_p != LIT_CHAR_NULL)
602425bb815Sopenharmony_ci  {
603425bb815Sopenharmony_ci    if (*format_p != LIT_CHAR_DOLLAR_SIGN)
604425bb815Sopenharmony_ci    {
605425bb815Sopenharmony_ci      *dest_p++ = (lit_utf8_byte_t) *format_p++;
606425bb815Sopenharmony_ci      continue;
607425bb815Sopenharmony_ci    }
608425bb815Sopenharmony_ci
609425bb815Sopenharmony_ci    format_p++;
610425bb815Sopenharmony_ci
611425bb815Sopenharmony_ci    const char *str_p = NULL;
612425bb815Sopenharmony_ci    int32_t number = 0;
613425bb815Sopenharmony_ci    int32_t number_length = 0;
614425bb815Sopenharmony_ci
615425bb815Sopenharmony_ci    switch (*format_p)
616425bb815Sopenharmony_ci    {
617425bb815Sopenharmony_ci      case LIT_CHAR_UPPERCASE_Y: /* Year. */
618425bb815Sopenharmony_ci      {
619425bb815Sopenharmony_ci        number = (int32_t) ecma_date_year_from_time (datetime_number);
620425bb815Sopenharmony_ci
621425bb815Sopenharmony_ci        if (number >= 100000 || number <= -100000)
622425bb815Sopenharmony_ci        {
623425bb815Sopenharmony_ci          number_length = 6;
624425bb815Sopenharmony_ci        }
625425bb815Sopenharmony_ci        else if (number >= 10000 || number <= -10000)
626425bb815Sopenharmony_ci        {
627425bb815Sopenharmony_ci          number_length = 5;
628425bb815Sopenharmony_ci        }
629425bb815Sopenharmony_ci        else
630425bb815Sopenharmony_ci        {
631425bb815Sopenharmony_ci          number_length = 4;
632425bb815Sopenharmony_ci        }
633425bb815Sopenharmony_ci        break;
634425bb815Sopenharmony_ci      }
635425bb815Sopenharmony_ci      case LIT_CHAR_LOWERCASE_Y: /* ISO Year: -000001, 0000, 0001, 9999, +012345 */
636425bb815Sopenharmony_ci      {
637425bb815Sopenharmony_ci        number = (int32_t) ecma_date_year_from_time (datetime_number);
638425bb815Sopenharmony_ci        if (0 <= number && number <= 9999)
639425bb815Sopenharmony_ci        {
640425bb815Sopenharmony_ci          number_length = 4;
641425bb815Sopenharmony_ci        }
642425bb815Sopenharmony_ci        else
643425bb815Sopenharmony_ci        {
644425bb815Sopenharmony_ci          number_length = 6;
645425bb815Sopenharmony_ci        }
646425bb815Sopenharmony_ci        break;
647425bb815Sopenharmony_ci      }
648425bb815Sopenharmony_ci      case LIT_CHAR_UPPERCASE_M: /* Month. */
649425bb815Sopenharmony_ci      {
650425bb815Sopenharmony_ci        int32_t month = (int32_t) ecma_date_month_from_time (datetime_number);
651425bb815Sopenharmony_ci
652425bb815Sopenharmony_ci        JERRY_ASSERT (month >= 0 && month <= 11);
653425bb815Sopenharmony_ci
654425bb815Sopenharmony_ci        str_p = month_names_p[month];
655425bb815Sopenharmony_ci        break;
656425bb815Sopenharmony_ci      }
657425bb815Sopenharmony_ci      case LIT_CHAR_UPPERCASE_O: /* Month as number. */
658425bb815Sopenharmony_ci      {
659425bb815Sopenharmony_ci        /* The 'ecma_date_month_from_time' (ECMA 262 v5, 15.9.1.4) returns a
660425bb815Sopenharmony_ci         * number from 0 to 11, but we have to print the month from 1 to 12
661425bb815Sopenharmony_ci         * for ISO 8601 standard (ECMA 262 v5, 15.9.1.15). */
662425bb815Sopenharmony_ci        number = ((int32_t) ecma_date_month_from_time (datetime_number)) + 1;
663425bb815Sopenharmony_ci        number_length = 2;
664425bb815Sopenharmony_ci        break;
665425bb815Sopenharmony_ci      }
666425bb815Sopenharmony_ci      case LIT_CHAR_UPPERCASE_D: /* Day. */
667425bb815Sopenharmony_ci      {
668425bb815Sopenharmony_ci        number = (int32_t) ecma_date_date_from_time (datetime_number);
669425bb815Sopenharmony_ci        number_length = 2;
670425bb815Sopenharmony_ci        break;
671425bb815Sopenharmony_ci      }
672425bb815Sopenharmony_ci      case LIT_CHAR_UPPERCASE_W: /* Day of week. */
673425bb815Sopenharmony_ci      {
674425bb815Sopenharmony_ci        int32_t day = (int32_t) ecma_date_week_day (datetime_number);
675425bb815Sopenharmony_ci
676425bb815Sopenharmony_ci        JERRY_ASSERT (day >= 0 && day <= 6);
677425bb815Sopenharmony_ci
678425bb815Sopenharmony_ci        str_p = day_names_p[day];
679425bb815Sopenharmony_ci        break;
680425bb815Sopenharmony_ci      }
681425bb815Sopenharmony_ci      case LIT_CHAR_LOWERCASE_H: /* Hour. */
682425bb815Sopenharmony_ci      {
683425bb815Sopenharmony_ci        number = (int32_t) ecma_date_hour_from_time (datetime_number);
684425bb815Sopenharmony_ci        number_length = 2;
685425bb815Sopenharmony_ci        break;
686425bb815Sopenharmony_ci      }
687425bb815Sopenharmony_ci      case LIT_CHAR_LOWERCASE_M: /* Minutes. */
688425bb815Sopenharmony_ci      {
689425bb815Sopenharmony_ci        number = (int32_t) ecma_date_min_from_time (datetime_number);
690425bb815Sopenharmony_ci        number_length = 2;
691425bb815Sopenharmony_ci        break;
692425bb815Sopenharmony_ci      }
693425bb815Sopenharmony_ci      case LIT_CHAR_LOWERCASE_S: /* Seconds. */
694425bb815Sopenharmony_ci      {
695425bb815Sopenharmony_ci        number = (int32_t) ecma_date_sec_from_time (datetime_number);
696425bb815Sopenharmony_ci        number_length = 2;
697425bb815Sopenharmony_ci        break;
698425bb815Sopenharmony_ci      }
699425bb815Sopenharmony_ci      case LIT_CHAR_LOWERCASE_I: /* Milliseconds. */
700425bb815Sopenharmony_ci      {
701425bb815Sopenharmony_ci        number = (int32_t) ecma_date_ms_from_time (datetime_number);
702425bb815Sopenharmony_ci        number_length = 3;
703425bb815Sopenharmony_ci        break;
704425bb815Sopenharmony_ci      }
705425bb815Sopenharmony_ci      case LIT_CHAR_LOWERCASE_Z: /* Time zone hours part. */
706425bb815Sopenharmony_ci      {
707425bb815Sopenharmony_ci        int32_t time_zone = (int32_t) ecma_date_local_time_zone_adjustment (datetime_number);
708425bb815Sopenharmony_ci
709425bb815Sopenharmony_ci        if (time_zone >= 0)
710425bb815Sopenharmony_ci        {
711425bb815Sopenharmony_ci          *dest_p++ = LIT_CHAR_PLUS;
712425bb815Sopenharmony_ci        }
713425bb815Sopenharmony_ci        else
714425bb815Sopenharmony_ci        {
715425bb815Sopenharmony_ci          *dest_p++ = LIT_CHAR_MINUS;
716425bb815Sopenharmony_ci          time_zone = -time_zone;
717425bb815Sopenharmony_ci        }
718425bb815Sopenharmony_ci
719425bb815Sopenharmony_ci        number = time_zone / (int32_t) ECMA_DATE_MS_PER_HOUR;
720425bb815Sopenharmony_ci        number_length = 2;
721425bb815Sopenharmony_ci        break;
722425bb815Sopenharmony_ci      }
723425bb815Sopenharmony_ci      default:
724425bb815Sopenharmony_ci      {
725425bb815Sopenharmony_ci        JERRY_ASSERT (*format_p == LIT_CHAR_UPPERCASE_Z); /* Time zone minutes part. */
726425bb815Sopenharmony_ci
727425bb815Sopenharmony_ci        int32_t time_zone = (int32_t) ecma_date_local_time_zone_adjustment (datetime_number);
728425bb815Sopenharmony_ci
729425bb815Sopenharmony_ci        if (time_zone < 0)
730425bb815Sopenharmony_ci        {
731425bb815Sopenharmony_ci          time_zone = -time_zone;
732425bb815Sopenharmony_ci        }
733425bb815Sopenharmony_ci
734425bb815Sopenharmony_ci        number = time_zone % (int32_t) ECMA_DATE_MS_PER_HOUR / (int32_t) ECMA_DATE_MS_PER_MINUTE;
735425bb815Sopenharmony_ci        number_length = 2;
736425bb815Sopenharmony_ci        break;
737425bb815Sopenharmony_ci      }
738425bb815Sopenharmony_ci    }
739425bb815Sopenharmony_ci
740425bb815Sopenharmony_ci    format_p++;
741425bb815Sopenharmony_ci
742425bb815Sopenharmony_ci    if (str_p != NULL)
743425bb815Sopenharmony_ci    {
744425bb815Sopenharmony_ci      /* Print string values: month or day name which is always 3 characters */
745425bb815Sopenharmony_ci      memcpy (dest_p, str_p, 3);
746425bb815Sopenharmony_ci      dest_p += 3;
747425bb815Sopenharmony_ci      continue;
748425bb815Sopenharmony_ci    }
749425bb815Sopenharmony_ci
750425bb815Sopenharmony_ci    /* Print right aligned number values. */
751425bb815Sopenharmony_ci    JERRY_ASSERT (number_length > 0);
752425bb815Sopenharmony_ci
753425bb815Sopenharmony_ci    if (number < 0)
754425bb815Sopenharmony_ci    {
755425bb815Sopenharmony_ci      number = -number;
756425bb815Sopenharmony_ci      *dest_p++ = '-';
757425bb815Sopenharmony_ci    }
758425bb815Sopenharmony_ci    else if (*(format_p - 1) == LIT_CHAR_LOWERCASE_Y && number_length == 6)
759425bb815Sopenharmony_ci    {
760425bb815Sopenharmony_ci      /* positive sign is compulsory for extended years */
761425bb815Sopenharmony_ci      *dest_p++ = '+';
762425bb815Sopenharmony_ci    }
763425bb815Sopenharmony_ci
764425bb815Sopenharmony_ci    dest_p += number_length;
765425bb815Sopenharmony_ci    lit_utf8_byte_t *buffer_p = dest_p;
766425bb815Sopenharmony_ci
767425bb815Sopenharmony_ci    do
768425bb815Sopenharmony_ci    {
769425bb815Sopenharmony_ci      buffer_p--;
770425bb815Sopenharmony_ci      *buffer_p = (lit_utf8_byte_t) ((number % 10) + (int32_t) LIT_CHAR_0);
771425bb815Sopenharmony_ci      number /= 10;
772425bb815Sopenharmony_ci    }
773425bb815Sopenharmony_ci    while (--number_length);
774425bb815Sopenharmony_ci  }
775425bb815Sopenharmony_ci
776425bb815Sopenharmony_ci  JERRY_ASSERT (dest_p <= date_buffer + date_buffer_length);
777425bb815Sopenharmony_ci
778425bb815Sopenharmony_ci  return ecma_make_string_value (ecma_new_ecma_string_from_utf8 (date_buffer,
779425bb815Sopenharmony_ci                                                                 (lit_utf8_size_t) (dest_p - date_buffer)));
780425bb815Sopenharmony_ci} /* ecma_date_to_string_format */
781425bb815Sopenharmony_ci
782425bb815Sopenharmony_ci/**
783425bb815Sopenharmony_ci * Common function to create a time zone specific string from a numeric value.
784425bb815Sopenharmony_ci *
785425bb815Sopenharmony_ci * Used by:
786425bb815Sopenharmony_ci *        - The Date routine.
787425bb815Sopenharmony_ci *        - The Date.prototype.toString routine.
788425bb815Sopenharmony_ci *
789425bb815Sopenharmony_ci * @return ecma value
790425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
791425bb815Sopenharmony_ci */
792425bb815Sopenharmony_ciecma_value_t
793425bb815Sopenharmony_ciecma_date_value_to_string (ecma_number_t datetime_number) /**< datetime */
794425bb815Sopenharmony_ci{
795425bb815Sopenharmony_ci  datetime_number += ecma_date_local_time_zone_adjustment (datetime_number);
796425bb815Sopenharmony_ci  return ecma_date_to_string_format (datetime_number, "$W $M $D $Y $h:$m:$s GMT$z$Z");
797425bb815Sopenharmony_ci} /* ecma_date_value_to_string */
798425bb815Sopenharmony_ci
799425bb815Sopenharmony_ci/**
800425bb815Sopenharmony_ci * Common function to create a time zone specific string from a numeric value.
801425bb815Sopenharmony_ci *
802425bb815Sopenharmony_ci * Used by:
803425bb815Sopenharmony_ci *        - The Date.prototype.toUTCString routine.
804425bb815Sopenharmony_ci *
805425bb815Sopenharmony_ci * @return ecma value
806425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
807425bb815Sopenharmony_ci */
808425bb815Sopenharmony_ciecma_value_t
809425bb815Sopenharmony_ciecma_date_value_to_utc_string (ecma_number_t datetime_number) /**< datetime */
810425bb815Sopenharmony_ci{
811425bb815Sopenharmony_ci  return ecma_date_to_string_format (datetime_number, "$W, $D $M $Y $h:$m:$s GMT");
812425bb815Sopenharmony_ci} /* ecma_date_value_to_utc_string */
813425bb815Sopenharmony_ci
814425bb815Sopenharmony_ci/**
815425bb815Sopenharmony_ci * Common function to create a ISO specific string from a numeric value.
816425bb815Sopenharmony_ci *
817425bb815Sopenharmony_ci * Used by:
818425bb815Sopenharmony_ci *        - The Date.prototype.toISOString routine.
819425bb815Sopenharmony_ci *
820425bb815Sopenharmony_ci * @return ecma value
821425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
822425bb815Sopenharmony_ci */
823425bb815Sopenharmony_ciecma_value_t
824425bb815Sopenharmony_ciecma_date_value_to_iso_string (ecma_number_t datetime_number) /**<datetime */
825425bb815Sopenharmony_ci{
826425bb815Sopenharmony_ci  return ecma_date_to_string_format (datetime_number, "$y-$O-$DT$h:$m:$s.$iZ");
827425bb815Sopenharmony_ci} /* ecma_date_value_to_iso_string */
828425bb815Sopenharmony_ci
829425bb815Sopenharmony_ci/**
830425bb815Sopenharmony_ci * Common function to create a date string from a numeric value.
831425bb815Sopenharmony_ci *
832425bb815Sopenharmony_ci * Used by:
833425bb815Sopenharmony_ci *        - The Date.prototype.toDateString routine.
834425bb815Sopenharmony_ci *
835425bb815Sopenharmony_ci * @return ecma value
836425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
837425bb815Sopenharmony_ci */
838425bb815Sopenharmony_ciecma_value_t
839425bb815Sopenharmony_ciecma_date_value_to_date_string (ecma_number_t datetime_number) /**<datetime */
840425bb815Sopenharmony_ci{
841425bb815Sopenharmony_ci  return ecma_date_to_string_format (datetime_number, "$Y-$O-$D");
842425bb815Sopenharmony_ci} /* ecma_date_value_to_date_string */
843425bb815Sopenharmony_ci
844425bb815Sopenharmony_ci/**
845425bb815Sopenharmony_ci * Common function to create a time string from a numeric value.
846425bb815Sopenharmony_ci *
847425bb815Sopenharmony_ci * Used by:
848425bb815Sopenharmony_ci *        - The Date.prototype.toTimeString routine.
849425bb815Sopenharmony_ci *
850425bb815Sopenharmony_ci * @return ecma value
851425bb815Sopenharmony_ci *         Returned value must be freed with ecma_free_value.
852425bb815Sopenharmony_ci */
853425bb815Sopenharmony_ciecma_value_t
854425bb815Sopenharmony_ciecma_date_value_to_time_string (ecma_number_t datetime_number) /**<datetime */
855425bb815Sopenharmony_ci{
856425bb815Sopenharmony_ci  return ecma_date_to_string_format (datetime_number, "$h:$m:$s.$i");
857425bb815Sopenharmony_ci} /* ecma_date_value_to_time_string */
858425bb815Sopenharmony_ci
859425bb815Sopenharmony_ci/**
860425bb815Sopenharmony_ci * @}
861425bb815Sopenharmony_ci * @}
862425bb815Sopenharmony_ci */
863425bb815Sopenharmony_ci
864425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_DATE) */
865