mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
- Optimize year from time calculation - Force arithmetic operations to int32_t/int64_t whenever possible - Optimize number conversion in date parse - Cache local TZA of the date object - Fix a bug in Date.parse timezone parsing JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik robert.fancsik@h-lab.eu
770 lines
19 KiB
C
770 lines
19 KiB
C
/* Copyright JS Foundation and other contributors, http://js.foundation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <math.h>
|
|
|
|
#include "ecma-alloc.h"
|
|
#include "ecma-builtin-helpers.h"
|
|
#include "ecma-exceptions.h"
|
|
#include "ecma-globals.h"
|
|
#include "ecma-helpers.h"
|
|
#include "ecma-objects.h"
|
|
#include "lit-char-helpers.h"
|
|
|
|
#if JERRY_BUILTIN_DATE
|
|
|
|
/** \addtogroup ecma ECMA
|
|
* @{
|
|
*
|
|
* \addtogroup ecmabuiltinhelpers ECMA builtin helper operations
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* Day names
|
|
*/
|
|
const char day_names_p[7][3] =
|
|
{
|
|
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
|
};
|
|
|
|
/**
|
|
* Month names
|
|
*/
|
|
const char month_names_p[12][3] =
|
|
{
|
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
|
};
|
|
|
|
/**
|
|
* Calculate the elapsed days since Unix Epoch
|
|
*
|
|
* @return elapsed days since Unix Epoch
|
|
*/
|
|
extern inline int32_t JERRY_ATTR_ALWAYS_INLINE
|
|
ecma_date_day_from_time (ecma_number_t time) /**< time value */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (time));
|
|
|
|
if (time < 0)
|
|
{
|
|
time -= ECMA_DATE_MS_PER_DAY - 1;
|
|
}
|
|
|
|
return (int32_t) (time / ECMA_DATE_MS_PER_DAY);
|
|
} /* ecma_date_day_from_time */
|
|
|
|
/**
|
|
* Abstract operation: DayFromYear
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.3
|
|
*
|
|
* @return first of day in the given year
|
|
*/
|
|
static int32_t
|
|
ecma_date_day_from_year (int32_t year) /**< year value */
|
|
{
|
|
if (JERRY_LIKELY (year >= 1970))
|
|
{
|
|
return (int32_t) (365 * (year - 1970)
|
|
+ ((year - 1969) / 4)
|
|
- ((year - 1901) / 100)
|
|
+ ((year - 1601) / 400));
|
|
}
|
|
|
|
return (int32_t) (365 * (year - 1970)
|
|
+ floor ((year - 1969) / 4.0)
|
|
- floor ((year - 1901) / 100.0)
|
|
+ floor ((year - 1601) / 400.0));
|
|
} /* ecma_date_day_from_year */
|
|
|
|
/**
|
|
* Abstract operation: DaysInYear
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.3
|
|
*
|
|
* @return number of days in the given year
|
|
*/
|
|
static int
|
|
ecma_date_days_in_year (int32_t year) /**< year */
|
|
{
|
|
if (year % 4 != 0
|
|
|| (year % 100 == 0 && (year % 400 != 0)))
|
|
{
|
|
return ECMA_DATE_DAYS_IN_YEAR;
|
|
}
|
|
|
|
return ECMA_DATE_DAYS_IN_LEAP_YEAR;
|
|
} /* ecma_date_days_in_year */
|
|
|
|
/**
|
|
* Abstract operation: InLeapYear
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.3
|
|
*
|
|
* @return 1 - if the year is leap
|
|
* 0 - otherwise
|
|
*/
|
|
static int32_t
|
|
ecma_date_in_leap_year (int32_t year) /**< time value */
|
|
{
|
|
return ecma_date_days_in_year (year) - ECMA_DATE_DAYS_IN_YEAR;
|
|
} /* ecma_date_in_leap_year */
|
|
|
|
/**
|
|
* First days of months in normal and leap years
|
|
*/
|
|
static const uint16_t first_day_in_month[2][12] =
|
|
{
|
|
{
|
|
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, /* normal year */
|
|
}
|
|
,
|
|
{
|
|
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 /* leap year */
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Abstract operation: YearFromTime
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.3
|
|
*
|
|
* @return year corresponds to the given time
|
|
*/
|
|
int32_t
|
|
ecma_date_year_from_time (ecma_number_t time) /**< time value */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (time));
|
|
|
|
int32_t approx = (int32_t) (floor (time / ECMA_DATE_MS_PER_DAY / 365.2425) + 1970);
|
|
int64_t year_ms = ecma_date_day_from_year (approx) * ((int64_t) ECMA_DATE_MS_PER_DAY);
|
|
|
|
if (year_ms > time)
|
|
{
|
|
approx--;
|
|
}
|
|
|
|
if (year_ms + ecma_date_days_in_year (approx) * ((int64_t) ECMA_DATE_MS_PER_DAY) <= time)
|
|
{
|
|
approx++;
|
|
}
|
|
|
|
return approx;
|
|
} /* ecma_date_year_from_time */
|
|
|
|
/**
|
|
* Abstract operation: MonthFromTime
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.4
|
|
*
|
|
* @return month corresponds to the given time
|
|
*/
|
|
int32_t
|
|
ecma_date_month_from_time (ecma_number_t time) /**< time value */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (time));
|
|
|
|
int32_t year = ecma_date_year_from_time (time);
|
|
int32_t day_within_year = ecma_date_day_from_time (time) - ecma_date_day_from_year (year);
|
|
|
|
JERRY_ASSERT (day_within_year >= 0 && day_within_year < ECMA_DATE_DAYS_IN_LEAP_YEAR);
|
|
|
|
int32_t in_leap_year = ecma_date_in_leap_year (year);
|
|
|
|
for (int i = 1; i < 12; i++)
|
|
{
|
|
if (day_within_year < first_day_in_month[in_leap_year][i])
|
|
{
|
|
return i - 1;
|
|
}
|
|
}
|
|
|
|
return 11;
|
|
} /* ecma_date_month_from_time */
|
|
|
|
/**
|
|
* Abstract operation: DateFromTime
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.4
|
|
*
|
|
* @return date corresponds to the given time
|
|
*/
|
|
int32_t
|
|
ecma_date_date_from_time (ecma_number_t time) /**< time value */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (time));
|
|
|
|
int32_t year = ecma_date_year_from_time (time);
|
|
int32_t day_within_year = ecma_date_day_from_time (time) - ecma_date_day_from_year (year);
|
|
|
|
JERRY_ASSERT (day_within_year >= 0 && day_within_year < ECMA_DATE_DAYS_IN_LEAP_YEAR);
|
|
|
|
int32_t in_leap_year = ecma_date_in_leap_year (year);
|
|
|
|
int32_t month = 11;
|
|
|
|
for (int i = 1; i < 12; i++)
|
|
{
|
|
if (day_within_year < first_day_in_month[in_leap_year][i])
|
|
{
|
|
month = i - 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return day_within_year + 1 - first_day_in_month[in_leap_year][month];
|
|
} /* ecma_date_date_from_time */
|
|
|
|
/**
|
|
* Abstract operation: WeekDay
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.4
|
|
*
|
|
* @return weekday corresponds to the given time
|
|
*/
|
|
int32_t
|
|
ecma_date_week_day (ecma_number_t time) /**< time value */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (time));
|
|
|
|
int32_t day = ecma_date_day_from_time (time);
|
|
|
|
int week_day = (day + 4) % 7;
|
|
|
|
return week_day >= 0 ? week_day : week_day + 7;
|
|
} /* ecma_date_week_day */
|
|
|
|
/**
|
|
* Abstract operation: LocalTZA
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.7
|
|
*
|
|
* @return local time zone adjustment
|
|
*/
|
|
extern inline ecma_number_t JERRY_ATTR_ALWAYS_INLINE
|
|
ecma_date_local_time_zone_adjustment (ecma_number_t time) /**< time value */
|
|
{
|
|
return jerry_port_get_local_time_zone_adjustment (time, true);
|
|
} /* ecma_date_local_time_zone_adjustment */
|
|
|
|
/**
|
|
* Abstract operation: UTC
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.9
|
|
*
|
|
* @return UTC time
|
|
*/
|
|
ecma_number_t
|
|
ecma_date_utc (ecma_number_t time) /**< time value */
|
|
{
|
|
return time - jerry_port_get_local_time_zone_adjustment (time, false);
|
|
} /* ecma_date_utc */
|
|
|
|
/**
|
|
* Calculate the time component from the given time
|
|
*
|
|
* @return time component of the given time
|
|
*/
|
|
int32_t
|
|
ecma_date_time_in_day_from_time (ecma_number_t time) /**< time value */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (time));
|
|
|
|
ecma_number_t day = ecma_date_day_from_time (time);
|
|
|
|
return (int32_t) (time - (day * ECMA_DATE_MS_PER_DAY));
|
|
} /* ecma_date_time_in_day_from_time */
|
|
|
|
/**
|
|
* Abstract operation: HourFromTime
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.10
|
|
*
|
|
* @return hours component of the given time
|
|
*/
|
|
int32_t
|
|
ecma_date_hour_from_time (ecma_number_t time) /**< time value */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (time));
|
|
|
|
int32_t time_in_day = ecma_date_time_in_day_from_time (time);
|
|
|
|
return (int32_t) (time_in_day / ECMA_DATE_MS_PER_HOUR);
|
|
} /* ecma_date_hour_from_time */
|
|
|
|
/**
|
|
* Abstract operation: HourFromTime
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.10
|
|
*
|
|
* @return minutes component of the given time
|
|
*/
|
|
int32_t
|
|
ecma_date_min_from_time (ecma_number_t time) /**< time value */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (time));
|
|
|
|
int32_t time_in_day = ecma_date_time_in_day_from_time (time);
|
|
|
|
return ((int32_t) (time_in_day / ECMA_DATE_MS_PER_MINUTE)) % ECMA_DATE_MINUTES_PER_HOUR;
|
|
} /* ecma_date_min_from_time */
|
|
|
|
/**
|
|
* Abstract operation: HourFromTime
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.10
|
|
*
|
|
* @return seconds component of the given time
|
|
*/
|
|
int32_t
|
|
ecma_date_sec_from_time (ecma_number_t time) /**< time value */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (time));
|
|
|
|
int32_t time_in_day = ecma_date_time_in_day_from_time (time);
|
|
|
|
return ((int32_t) (time_in_day / ECMA_DATE_MS_PER_SECOND)) % ECMA_DATE_SECONDS_PER_MINUTE;
|
|
} /* ecma_date_sec_from_time */
|
|
|
|
/**
|
|
* Abstract operation: HourFromTime
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.10
|
|
*
|
|
* @return milliseconds component of the given time
|
|
*/
|
|
int32_t
|
|
ecma_date_ms_from_time (ecma_number_t time) /**< time value */
|
|
{
|
|
JERRY_ASSERT (!ecma_number_is_nan (time));
|
|
|
|
int32_t time_in_day = ecma_date_time_in_day_from_time (time);
|
|
|
|
return (int32_t) (time_in_day % ECMA_DATE_MS_PER_SECOND);
|
|
} /* ecma_date_ms_from_time */
|
|
|
|
/**
|
|
* Abstract operation: MakeTime
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.11
|
|
*
|
|
* @return constructed time in milliseconds
|
|
*/
|
|
ecma_number_t
|
|
ecma_date_make_time (ecma_number_t hour, /**< hour value */
|
|
ecma_number_t min, /**< minute value */
|
|
ecma_number_t sec, /**< second value */
|
|
ecma_number_t ms) /**< millisecond value */
|
|
{
|
|
if (!ecma_number_is_finite (hour)
|
|
|| !ecma_number_is_finite (min)
|
|
|| !ecma_number_is_finite (sec)
|
|
|| !ecma_number_is_finite (ms))
|
|
{
|
|
return ecma_number_make_nan ();
|
|
}
|
|
|
|
ecma_number_t h = ecma_number_trunc (hour);
|
|
ecma_number_t m = ecma_number_trunc (min);
|
|
ecma_number_t s = ecma_number_trunc (sec);
|
|
ecma_number_t milli = ecma_number_trunc (ms);
|
|
|
|
return (ecma_number_t) ((h * ECMA_DATE_MS_PER_HOUR
|
|
+ m * ECMA_DATE_MS_PER_MINUTE
|
|
+ s * ECMA_DATE_MS_PER_SECOND
|
|
+ milli));
|
|
} /* ecma_date_make_time */
|
|
|
|
/**
|
|
* Abstract operation: MakeDay
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.12
|
|
*
|
|
* @return elpased number of days since Unix Epoch
|
|
*/
|
|
ecma_number_t
|
|
ecma_date_make_day (ecma_number_t year, /**< year value */
|
|
ecma_number_t month, /**< month value */
|
|
ecma_number_t date) /**< date value */
|
|
{
|
|
/* 1. */
|
|
if (!ecma_number_is_finite (year)
|
|
|| !ecma_number_is_finite (month)
|
|
|| !ecma_number_is_finite (date)
|
|
|| fabs (year) > INT32_MAX)
|
|
{
|
|
return ecma_number_make_nan ();
|
|
}
|
|
|
|
/* 2., 3., 4. */
|
|
int32_t y = (int32_t) (year);
|
|
ecma_number_t m = ecma_number_trunc (month);
|
|
ecma_number_t dt = ecma_number_trunc (date);
|
|
|
|
/* 5. */
|
|
int32_t ym = y + (int32_t) (floor (m / 12));
|
|
|
|
/* 6. */
|
|
int32_t mn = (int32_t) fmod (m, 12);
|
|
|
|
if (mn < 0)
|
|
{
|
|
mn += 12;
|
|
}
|
|
|
|
/* 7. */
|
|
ecma_number_t days = (ecma_date_day_from_year (ym)
|
|
+ first_day_in_month[ecma_date_in_leap_year (ym)][mn]
|
|
+ (dt - 1));
|
|
return days * ECMA_DATE_MS_PER_DAY;
|
|
} /* ecma_date_make_day */
|
|
|
|
/**
|
|
* Abstract operation: MakeTime
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.13
|
|
*
|
|
* @return elpased number of milliceconds since Unix Epoch
|
|
*/
|
|
ecma_number_t
|
|
ecma_date_make_date (ecma_number_t day, /**< day value */
|
|
ecma_number_t time) /**< time value */
|
|
{
|
|
if (!ecma_number_is_finite (day)
|
|
|| !ecma_number_is_finite (time))
|
|
{
|
|
return ecma_number_make_nan ();
|
|
}
|
|
|
|
return day + time;
|
|
} /* ecma_date_make_date */
|
|
|
|
/**
|
|
* Abstract operation: TimeClip
|
|
*
|
|
* See also:
|
|
* ECMA-262 v11, 20.4.1.14
|
|
*
|
|
* @return elpased number of milliceconds since Unix Epoch
|
|
*/
|
|
ecma_number_t
|
|
ecma_date_time_clip (ecma_number_t time) /**< time value */
|
|
{
|
|
if (!ecma_number_is_finite (time)
|
|
|| fabs (time) > ECMA_DATE_MAX_VALUE)
|
|
{
|
|
return ecma_number_make_nan ();
|
|
}
|
|
|
|
return ecma_number_trunc (time);
|
|
} /* ecma_date_time_clip */
|
|
|
|
/**
|
|
* Common function to convert date to string.
|
|
*
|
|
* @return ecma value
|
|
* Returned value must be freed with ecma_free_value.
|
|
*/
|
|
static ecma_value_t
|
|
ecma_date_to_string_format (ecma_number_t datetime_number, /**< datetime */
|
|
const char *format_p) /**< format buffer */
|
|
{
|
|
const uint32_t date_buffer_length = 37;
|
|
JERRY_VLA (lit_utf8_byte_t, date_buffer, date_buffer_length);
|
|
|
|
lit_utf8_byte_t *dest_p = date_buffer;
|
|
|
|
while (*format_p != LIT_CHAR_NULL)
|
|
{
|
|
if (*format_p != LIT_CHAR_DOLLAR_SIGN)
|
|
{
|
|
*dest_p++ = (lit_utf8_byte_t) *format_p++;
|
|
continue;
|
|
}
|
|
|
|
format_p++;
|
|
|
|
const char *str_p = NULL;
|
|
int32_t number = 0;
|
|
int32_t number_length = 0;
|
|
|
|
switch (*format_p)
|
|
{
|
|
case LIT_CHAR_UPPERCASE_Y: /* Year. */
|
|
{
|
|
number = ecma_date_year_from_time (datetime_number);
|
|
|
|
if (number >= 100000 || number <= -100000)
|
|
{
|
|
number_length = 6;
|
|
}
|
|
else if (number >= 10000 || number <= -10000)
|
|
{
|
|
number_length = 5;
|
|
}
|
|
else
|
|
{
|
|
number_length = 4;
|
|
}
|
|
break;
|
|
}
|
|
case LIT_CHAR_LOWERCASE_Y: /* ISO Year: -000001, 0000, 0001, 9999, +012345 */
|
|
{
|
|
number = ecma_date_year_from_time (datetime_number);
|
|
if (0 <= number && number <= 9999)
|
|
{
|
|
number_length = 4;
|
|
}
|
|
else
|
|
{
|
|
number_length = 6;
|
|
}
|
|
break;
|
|
}
|
|
case LIT_CHAR_UPPERCASE_M: /* Month. */
|
|
{
|
|
int32_t month = ecma_date_month_from_time (datetime_number);
|
|
|
|
JERRY_ASSERT (month >= 0 && month <= 11);
|
|
|
|
str_p = month_names_p[month];
|
|
break;
|
|
}
|
|
case LIT_CHAR_UPPERCASE_O: /* Month as number. */
|
|
{
|
|
/* The '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). */
|
|
number = ecma_date_month_from_time (datetime_number) + 1;
|
|
number_length = 2;
|
|
break;
|
|
}
|
|
case LIT_CHAR_UPPERCASE_D: /* Day. */
|
|
{
|
|
number = ecma_date_date_from_time (datetime_number);
|
|
number_length = 2;
|
|
break;
|
|
}
|
|
case LIT_CHAR_UPPERCASE_W: /* Day of week. */
|
|
{
|
|
int32_t day = ecma_date_week_day (datetime_number);
|
|
|
|
JERRY_ASSERT (day >= 0 && day <= 6);
|
|
|
|
str_p = day_names_p[day];
|
|
break;
|
|
}
|
|
case LIT_CHAR_LOWERCASE_H: /* Hour. */
|
|
{
|
|
number = ecma_date_hour_from_time (datetime_number);
|
|
number_length = 2;
|
|
break;
|
|
}
|
|
case LIT_CHAR_LOWERCASE_M: /* Minutes. */
|
|
{
|
|
number = ecma_date_min_from_time (datetime_number);
|
|
number_length = 2;
|
|
break;
|
|
}
|
|
case LIT_CHAR_LOWERCASE_S: /* Seconds. */
|
|
{
|
|
number = ecma_date_sec_from_time (datetime_number);
|
|
number_length = 2;
|
|
break;
|
|
}
|
|
case LIT_CHAR_LOWERCASE_I: /* Milliseconds. */
|
|
{
|
|
number = ecma_date_ms_from_time (datetime_number);
|
|
number_length = 3;
|
|
break;
|
|
}
|
|
case LIT_CHAR_LOWERCASE_Z: /* Time zone hours part. */
|
|
{
|
|
int32_t time_zone = (int32_t) ecma_date_local_time_zone_adjustment (datetime_number);
|
|
|
|
if (time_zone >= 0)
|
|
{
|
|
*dest_p++ = LIT_CHAR_PLUS;
|
|
}
|
|
else
|
|
{
|
|
*dest_p++ = LIT_CHAR_MINUS;
|
|
time_zone = -time_zone;
|
|
}
|
|
|
|
number = time_zone / ECMA_DATE_MS_PER_HOUR;
|
|
number_length = 2;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
JERRY_ASSERT (*format_p == LIT_CHAR_UPPERCASE_Z); /* Time zone minutes part. */
|
|
|
|
int32_t time_zone = (int32_t) ecma_date_local_time_zone_adjustment (datetime_number);
|
|
|
|
if (time_zone < 0)
|
|
{
|
|
time_zone = -time_zone;
|
|
}
|
|
|
|
number = (time_zone % ECMA_DATE_MS_PER_HOUR) / ECMA_DATE_MS_PER_MINUTE;
|
|
number_length = 2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
format_p++;
|
|
|
|
if (str_p != NULL)
|
|
{
|
|
/* Print string values: month or day name which is always 3 characters */
|
|
memcpy (dest_p, str_p, 3);
|
|
dest_p += 3;
|
|
continue;
|
|
}
|
|
|
|
/* Print right aligned number values. */
|
|
JERRY_ASSERT (number_length > 0);
|
|
|
|
if (number < 0)
|
|
{
|
|
number = -number;
|
|
*dest_p++ = '-';
|
|
}
|
|
else if (*(format_p - 1) == LIT_CHAR_LOWERCASE_Y && number_length == 6)
|
|
{
|
|
/* positive sign is compulsory for extended years */
|
|
*dest_p++ = '+';
|
|
}
|
|
|
|
dest_p += number_length;
|
|
lit_utf8_byte_t *buffer_p = dest_p;
|
|
|
|
do
|
|
{
|
|
buffer_p--;
|
|
*buffer_p = (lit_utf8_byte_t) ((number % 10) + (int32_t) LIT_CHAR_0);
|
|
number /= 10;
|
|
}
|
|
while (--number_length);
|
|
}
|
|
|
|
JERRY_ASSERT (dest_p <= date_buffer + date_buffer_length);
|
|
|
|
return ecma_make_string_value (ecma_new_ecma_string_from_utf8 (date_buffer,
|
|
(lit_utf8_size_t) (dest_p - date_buffer)));
|
|
} /* ecma_date_to_string_format */
|
|
|
|
/**
|
|
* Common function to create a time zone specific string from a numeric value.
|
|
*
|
|
* Used by:
|
|
* - The Date routine.
|
|
* - The Date.prototype.toString routine.
|
|
*
|
|
* @return ecma value
|
|
* Returned value must be freed with ecma_free_value.
|
|
*/
|
|
ecma_value_t
|
|
ecma_date_value_to_string (ecma_number_t datetime_number) /**< datetime */
|
|
{
|
|
datetime_number += ecma_date_local_time_zone_adjustment (datetime_number);
|
|
return ecma_date_to_string_format (datetime_number, "$W $M $D $Y $h:$m:$s GMT$z$Z");
|
|
} /* ecma_date_value_to_string */
|
|
|
|
/**
|
|
* Common function to create a time zone specific string from a numeric value.
|
|
*
|
|
* Used by:
|
|
* - The Date.prototype.toUTCString routine.
|
|
*
|
|
* @return ecma value
|
|
* Returned value must be freed with ecma_free_value.
|
|
*/
|
|
ecma_value_t
|
|
ecma_date_value_to_utc_string (ecma_number_t datetime_number) /**< datetime */
|
|
{
|
|
return ecma_date_to_string_format (datetime_number, "$W, $D $M $Y $h:$m:$s GMT");
|
|
} /* ecma_date_value_to_utc_string */
|
|
|
|
/**
|
|
* Common function to create a ISO specific string from a numeric value.
|
|
*
|
|
* Used by:
|
|
* - The Date.prototype.toISOString routine.
|
|
*
|
|
* @return ecma value
|
|
* Returned value must be freed with ecma_free_value.
|
|
*/
|
|
ecma_value_t
|
|
ecma_date_value_to_iso_string (ecma_number_t datetime_number) /**<datetime */
|
|
{
|
|
return ecma_date_to_string_format (datetime_number, "$y-$O-$DT$h:$m:$s.$iZ");
|
|
} /* ecma_date_value_to_iso_string */
|
|
|
|
/**
|
|
* Common function to create a date string from a numeric value.
|
|
*
|
|
* Used by:
|
|
* - The Date.prototype.toDateString routine.
|
|
*
|
|
* @return ecma value
|
|
* Returned value must be freed with ecma_free_value.
|
|
*/
|
|
ecma_value_t
|
|
ecma_date_value_to_date_string (ecma_number_t datetime_number) /**<datetime */
|
|
{
|
|
return ecma_date_to_string_format (datetime_number, "$W $M $D $Y");
|
|
} /* ecma_date_value_to_date_string */
|
|
|
|
/**
|
|
* Common function to create a time string from a numeric value.
|
|
*
|
|
* Used by:
|
|
* - The Date.prototype.toTimeString routine.
|
|
*
|
|
* @return ecma value
|
|
* Returned value must be freed with ecma_free_value.
|
|
*/
|
|
ecma_value_t
|
|
ecma_date_value_to_time_string (ecma_number_t datetime_number) /**<datetime */
|
|
{
|
|
return ecma_date_to_string_format (datetime_number, "$h:$m:$s GMT$z$Z");
|
|
} /* ecma_date_value_to_time_string */
|
|
|
|
/**
|
|
* @}
|
|
* @}
|
|
*/
|
|
|
|
#endif /* JERRY_BUILTIN_DATE */
|