/**
 * The Date.prototype object's 'setUTCSeconds' routine
 *
 * See also:
 *          ECMA-262 v5, 15.9.5.31
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_date_prototype_set_utc_seconds (ecma_value_t this_arg, /**< this argument */
                                             ecma_value_t sec, /**< second */
                                             ecma_value_t ms) /**< millisecond */
{
  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  /* 1. */
  ECMA_TRY_CATCH (this_time_value, ecma_builtin_date_prototype_get_time (this_arg), ret_value);
  ecma_number_t t = *ecma_get_number_from_value (this_time_value);

  /* 2. */
  ECMA_OP_TO_NUMBER_TRY_CATCH (s, sec, ret_value);

  /* 3. */
  ECMA_OP_TO_NUMBER_TRY_CATCH (milli, ms, ret_value);
  if (ecma_is_value_undefined (ms))
  {
    milli = ecma_date_ms_from_time (t);
  }

  /* 4-7. */
  ecma_number_t hour = ecma_date_hour_from_time (t);
  ecma_number_t min = ecma_date_min_from_time (t);
  ret_value = ecma_date_set_internal_property (this_arg,
                                               ecma_date_day (t),
                                               ecma_date_make_time (hour, min, s, milli),
                                               ECMA_DATE_UTC);

  ECMA_OP_TO_NUMBER_FINALIZE (milli);
  ECMA_OP_TO_NUMBER_FINALIZE (s);
  ECMA_FINALIZE (this_time_value);

  return ret_value;
} /* ecma_builtin_date_prototype_set_utc_seconds */
/**
 * The Date.prototype object's 'setMilliseconds' routine
 *
 * See also:
 *          ECMA-262 v5, 15.9.5.28
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_date_prototype_set_milliseconds (ecma_value_t this_arg, /**< this argument */
                                              ecma_value_t ms) /**< millisecond */
{
  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  /* 1. */
  ECMA_TRY_CATCH (this_time_value, ecma_builtin_date_prototype_get_time (this_arg), ret_value);
  ecma_number_t t = ecma_date_local_time (*ecma_get_number_from_value (this_time_value));

  /* 2. */
  ECMA_OP_TO_NUMBER_TRY_CATCH (milli, ms, ret_value);

  /* 3-5. */
  ecma_number_t hour = ecma_date_hour_from_time (t);
  ecma_number_t min = ecma_date_min_from_time (t);
  ecma_number_t sec = ecma_date_sec_from_time (t);
  ret_value = ecma_date_set_internal_property (this_arg,
                                               ecma_date_day (t),
                                               ecma_date_make_time (hour, min, sec, milli),
                                               ECMA_DATE_LOCAL);

  ECMA_OP_TO_NUMBER_FINALIZE (milli);
  ECMA_FINALIZE (this_time_value);

  return ret_value;
} /* ecma_builtin_date_prototype_set_milliseconds */
/**
 * The Date.prototype object's 'setUTCMilliseconds' routine
 *
 * See also:
 *          ECMA-262 v5, 15.9.5.29
 *
 * @return completion value
 *         Returned value must be freed with ecma_free_completion_value.
 */
static ecma_completion_value_t
ecma_builtin_date_prototype_set_utc_milliseconds (ecma_value_t this_arg, /**< this argument */
                                                  ecma_value_t ms) /**< millisecond */
{
  ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();

  /* 1. */
  ECMA_TRY_CATCH (this_time_value, ecma_builtin_date_prototype_get_time (this_arg), ret_value);
  ecma_number_t t = *ecma_get_number_from_value (this_time_value);

  /* 2. */
  ECMA_OP_TO_NUMBER_TRY_CATCH (milli, ms, ret_value);

  /* 3-5. */
  ecma_number_t hour = ecma_date_hour_from_time (t);
  ecma_number_t min = ecma_date_min_from_time (t);
  ecma_number_t sec = ecma_date_sec_from_time (t);
  ret_value = ecma_date_set_internal_property (this_arg,
                                               ecma_date_day (t),
                                               ecma_date_make_time (hour, min, sec, milli),
                                               ECMA_DATE_UTC);

  ECMA_OP_TO_NUMBER_FINALIZE (milli);
  ECMA_FINALIZE (this_time_value);

  return ret_value;
} /* ecma_builtin_date_prototype_set_utc_milliseconds */
/**
 * The Date.prototype object's 'setUTCMinutes' routine
 *
 * See also:
 *          ECMA-262 v5, 15.9.5.33
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_date_prototype_set_utc_minutes (ecma_value_t this_arg, /**< this argument */
                                             const ecma_value_t args[], /**< arguments list */
                                             ecma_length_t args_number) /**< number of arguments */
{
  ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);

  /* 1. */
  ECMA_TRY_CATCH (this_time_value, ecma_builtin_date_prototype_get_time (this_arg), ret_value);
  ecma_number_t t = *ecma_get_number_from_value (this_time_value);

  /* 2. */
  ecma_number_t m = ecma_number_make_nan ();
  ecma_number_t s = ecma_date_sec_from_time (t);
  ecma_number_t milli = ecma_date_ms_from_time (t);
  if (args_number > 0 && !ecma_is_value_undefined (args[0]))
  {
    ECMA_OP_TO_NUMBER_TRY_CATCH (min, args[0], ret_value);
    m = min;

    /* 3. */
    if (args_number > 1 && !ecma_is_value_undefined (args[1]))
    {
      ECMA_OP_TO_NUMBER_TRY_CATCH (sec, args[1], ret_value);
      s = sec;

      /* 4. */
      if (args_number > 2 && !ecma_is_value_undefined (args[2]))
      {
        ECMA_OP_TO_NUMBER_TRY_CATCH (ms, args[2], ret_value);
        milli = ms;
        ECMA_OP_TO_NUMBER_FINALIZE (ms);
      }
      ECMA_OP_TO_NUMBER_FINALIZE (sec);
    }
    ECMA_OP_TO_NUMBER_FINALIZE (min);
  }

  if (ecma_is_value_empty (ret_value))
  {
    /* 5-8. */
    ecma_number_t hour = ecma_date_hour_from_time (t);
    ret_value = ecma_date_set_internal_property (this_arg,
                                                 ecma_date_day (t),
                                                 ecma_date_make_time (hour, m, s, milli),
                                                 ECMA_DATE_UTC);
  }
  ECMA_FINALIZE (this_time_value);

  return ret_value;
} /* ecma_builtin_date_prototype_set_utc_minutes */
/**
 * Unit test's main function.
 */
int
main ()
{
  /* int ecma_date_day (time)*/

  TEST_ASSERT (ecma_date_day (0) == 0);
  TEST_ASSERT (ecma_date_day (MS_PER_DAY) == 1);

  /* ecma_number_t ecma_date_time_within_day (time) */

  TEST_ASSERT (ecma_date_time_within_day (0) == 0);
  TEST_ASSERT (ecma_date_time_within_day (42) == 42);
  TEST_ASSERT (ecma_date_time_within_day (42.51) == 42.51);
  TEST_ASSERT (ecma_date_time_within_day (MS_PER_DAY + 42) == 42);

  /* int ecma_date_days_in_year (year) */

  TEST_ASSERT (ecma_date_days_in_year (0) == 366);
  TEST_ASSERT (ecma_date_days_in_year (1600) == 366);
  TEST_ASSERT (ecma_date_days_in_year (1603) == 365);
  TEST_ASSERT (ecma_date_days_in_year (1900) == 365);
  TEST_ASSERT (ecma_date_days_in_year (1970) == 365);
  TEST_ASSERT (ecma_date_days_in_year (2000) == 366);
  TEST_ASSERT (ecma_date_days_in_year (2000.45) == 366);
  TEST_ASSERT (ecma_date_days_in_year (2012) == 366);
  TEST_ASSERT (ecma_date_days_in_year (2015) == 365);
  TEST_ASSERT (ecma_date_days_in_year (285616 + 1970) == 365);
  TEST_ASSERT (ecma_date_days_in_year (-1970) == 365);

  /* int ecma_date_day_from_year (year) */

  TEST_ASSERT (ecma_date_day_from_year (1969) == -365);
  TEST_ASSERT (ecma_date_day_from_year (1970) == 0);
  TEST_ASSERT (ecma_date_day_from_year (1971) == 365);
  TEST_ASSERT (ecma_date_day_from_year (2000) == 10957);

  /* int ecma_date_year_from_time (time) */

  TEST_ASSERT (ecma_date_year_from_time (0) == 1970);
  TEST_ASSERT (ecma_date_year_from_time (0) == 1970);
  TEST_ASSERT (ecma_date_year_from_time (MS_PER_DAY) == 1970);
  TEST_ASSERT (ecma_date_year_from_time ((MS_PER_DAY) * (ecma_number_t) 365 - 1) == 1970);
  TEST_ASSERT (ecma_date_year_from_time (MS_PER_DAY * (ecma_number_t) 365) == 1971);
  TEST_ASSERT (ecma_date_year_from_time (MS_PER_DAY * (ecma_number_t) (365 * (2015 - 1970)))
                == 2014);
  TEST_ASSERT (ecma_date_year_from_time (MS_PER_DAY * (ecma_number_t) (365.25 * (2015 - 1970)))
                == 2015);
  TEST_ASSERT (ecma_date_year_from_time (-MS_PER_YEAR) == 1969);
  TEST_ASSERT (ecma_date_year_from_time (-1970 * MS_PER_YEAR) == 1);
  TEST_ASSERT (ecma_date_year_from_time (START_OF_GREGORIAN_CALENDAR) == 0);
  TEST_ASSERT (ecma_date_year_from_time (START_OF_GREGORIAN_CALENDAR - 1) == -1);
  TEST_ASSERT (ecma_date_year_from_time (START_OF_GREGORIAN_CALENDAR - 3 * MS_PER_YEAR) == -3);

  /* int ecma_date_day_within_year (time) */

  /* FIXME: Implement */

  /* int ecma_date_month_from_time  (time) */

  TEST_ASSERT (ecma_date_month_from_time (START_OF_GREGORIAN_CALENDAR) == 0);
  TEST_ASSERT (ecma_date_month_from_time (0) == 0);
  TEST_ASSERT (ecma_date_month_from_time (-MS_PER_DAY) == 11);
  TEST_ASSERT (ecma_date_month_from_time (31 * MS_PER_DAY) == 1);

  /* int ecma_date_date_from_time  (time) */

  TEST_ASSERT (ecma_date_date_from_time (START_OF_GREGORIAN_CALENDAR) == 1);
  TEST_ASSERT (ecma_date_date_from_time (0) == 1);
  TEST_ASSERT (ecma_date_date_from_time (-MS_PER_DAY) == 31);
  TEST_ASSERT (ecma_date_date_from_time (31 * MS_PER_DAY) == 1);

  /* int ecma_date_week_day (ecma_number_t time) */

  /* FIXME: Implement */

  /* ecma_number_t ecma_date_local_tza () */

  /* FIXME: Implement */

  /* ecma_number_t ecma_date_daylight_saving_ta (time) */

  /* FIXME: Implement */

  /* ecma_number_t ecma_date_local_time (time) */

  /* FIXME: Implement */

  /* ecma_number_t ecma_date_utc (time) */

  /* FIXME: Implement */

  /* ecma_number_t ecma_date_hour_from_time (time) */

  TEST_ASSERT (ecma_date_hour_from_time (START_OF_GREGORIAN_CALENDAR) == 0);
  TEST_ASSERT (ecma_date_hour_from_time (0) == 0);
  TEST_ASSERT (ecma_date_hour_from_time (-MS_PER_DAY) == 0);
  TEST_ASSERT (ecma_date_hour_from_time (-1) == 23);

  /* ecma_number_t ecma_date_min_from_time (time) */

  TEST_ASSERT (ecma_date_min_from_time (START_OF_GREGORIAN_CALENDAR) == 0);
  TEST_ASSERT (ecma_date_min_from_time (0) == 0);
  TEST_ASSERT (ecma_date_min_from_time (-MS_PER_DAY) == 0);
  TEST_ASSERT (ecma_date_min_from_time (-1) == 59);

  /* ecma_number_t ecma_date_sec_from_time (time) */

  TEST_ASSERT (ecma_date_sec_from_time (START_OF_GREGORIAN_CALENDAR) == 0);
  TEST_ASSERT (ecma_date_sec_from_time (0) == 0);
  TEST_ASSERT (ecma_date_sec_from_time (-MS_PER_DAY) == 0);
  TEST_ASSERT (ecma_date_sec_from_time (-1) == 59);

  /* ecma_number_t ecma_date_ms_from_time (time) */

  TEST_ASSERT (ecma_date_ms_from_time (START_OF_GREGORIAN_CALENDAR) == 0);
  TEST_ASSERT (ecma_date_ms_from_time (0) == 0);
  TEST_ASSERT (ecma_date_ms_from_time (-MS_PER_DAY) == 0);
  TEST_ASSERT (ecma_date_ms_from_time (-1) == 999);

  /* ecma_number_t ecma_date_make_time (hour, min, sec, ms) */

  /* FIXME: Implement */

  /* ecma_number_t ecma_date_make_day (year, month, date) */

  TEST_ASSERT (ecma_date_make_day (1970, 0, 1) == 0);
  TEST_ASSERT (ecma_date_make_day (1970, -1, 1) == -31);
  TEST_ASSERT (ecma_date_make_day (1970, 0, 2.5) == 1);
  TEST_ASSERT (ecma_date_make_day (1970, 1, 35) == 65);
  TEST_ASSERT (ecma_date_make_day (1970, 13, 35) == 430);
  TEST_ASSERT (ecma_date_make_day (2016, 2, 1) == 16861);

  /* ecma_number_t ecma_date_make_date (day, time) */

  /* FIXME: Implement */

  /* ecma_number_t ecma_date_time_clip (year) */

  /* FIXME: Implement */

  return 0;
} /* main */
/**
 * Dispatch set date functions
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_date_prototype_dispatch_set (uint16_t builtin_routine_id, /**< built-in wide routine
                                                                        *   identifier */
                                          ecma_extended_object_t *ext_object_p, /**< date extended object */
                                          ecma_number_t date_num, /**< date converted to number */
                                          const ecma_value_t arguments_list[], /**< list of arguments
                                                                                *   passed to routine */
                                          ecma_length_t arguments_number) /**< length of arguments' list */
{
  ecma_number_t converted_number[4];
  ecma_length_t conversions = 0;

  /* If the first argument is not specified, it is always converted to NaN. */
  converted_number[0] = ecma_number_make_nan ();

  switch (builtin_routine_id)
  {
#ifndef CONFIG_DISABLE_ANNEXB_BUILTIN
    case ECMA_DATE_PROTOTYPE_SET_YEAR:
#endif /* !CONFIG_DISABLE_ANNEXB_BUILTIN */
    case ECMA_DATE_PROTOTYPE_SET_DATE:
    case ECMA_DATE_PROTOTYPE_SET_UTC_DATE:
    case ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS:
    case ECMA_DATE_PROTOTYPE_SET_MILLISECONDS:
    {
      conversions = 1;
      break;
    }
    case ECMA_DATE_PROTOTYPE_SET_MONTH:
    case ECMA_DATE_PROTOTYPE_SET_UTC_MONTH:
    case ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS:
    case ECMA_DATE_PROTOTYPE_SET_SECONDS:
    {
      conversions = 2;
      break;
    }
    case ECMA_DATE_PROTOTYPE_SET_FULL_YEAR:
    case ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR:
    case ECMA_DATE_PROTOTYPE_SET_MINUTES:
    case ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES:
    {
      conversions = 3;
      break;
    }
    default:
    {
      JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_HOURS
                    || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_HOURS);
      conversions = 4;
      break;
    }
  }

  if (conversions > arguments_number)
  {
    conversions = arguments_number;
  }

  for (ecma_length_t i = 0; i < conversions; i++)
  {
    ecma_value_t value = ecma_op_to_number (arguments_list[i]);

    if (ECMA_IS_VALUE_ERROR (value))
    {
      return value;
    }

    converted_number[i] = ecma_get_number_from_value (value);
    ecma_free_value (value);
  }

  ecma_number_t day_part;
  ecma_number_t time_part;

  if (builtin_routine_id <= ECMA_DATE_PROTOTYPE_SET_UTC_DATE)
  {
    if (ecma_number_is_nan (date_num))
    {
      if (ECMA_DATE_PROTOTYPE_IS_SET_YEAR_ROUTINE (builtin_routine_id))
      {
        date_num = ECMA_NUMBER_ZERO;
      }
      else
      {
        return ecma_make_number_value (date_num);
      }
    }

    time_part = ecma_date_time_within_day (date_num);

    ecma_number_t year = ecma_date_year_from_time (date_num);
    ecma_number_t month = ecma_date_month_from_time (date_num);
    ecma_number_t day = ecma_date_date_from_time (date_num);

    switch (builtin_routine_id)
    {
      case ECMA_DATE_PROTOTYPE_SET_FULL_YEAR:
      case ECMA_DATE_PROTOTYPE_SET_UTC_FULL_YEAR:
      {
        year = converted_number[0];
        if (conversions >= 2)
        {
          month = converted_number[1];
        }
        if (conversions >= 3)
        {
          day = converted_number[2];
        }
        break;
      }
#ifndef CONFIG_DISABLE_ANNEXB_BUILTIN
      case ECMA_DATE_PROTOTYPE_SET_YEAR:
      {
        year = converted_number[0];
        if (year >= 0 && year <= 99)
        {
          year += 1900;
        }
        break;
      }
#endif /* !CONFIG_DISABLE_ANNEXB_BUILTIN */
      case ECMA_DATE_PROTOTYPE_SET_MONTH:
      case ECMA_DATE_PROTOTYPE_SET_UTC_MONTH:
      {
        month = converted_number[0];
        if (conversions >= 2)
        {
          day = converted_number[1];
        }
        break;
      }
      default:
      {
        JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_DATE
                      || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_DATE);
        day = converted_number[0];
        break;
      }
    }

    day_part = ecma_date_make_day (year, month, day);

#ifndef CONFIG_DISABLE_ANNEXB_BUILTIN
    if (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_YEAR)
    {
      builtin_routine_id = ECMA_DATE_PROTOTYPE_SET_UTC_YEAR;

      if (ecma_number_is_nan (converted_number[0]))
      {
        day_part = 0;
        time_part = converted_number[0];
      }
    }
#endif /* !CONFIG_DISABLE_ANNEXB_BUILTIN */
  }
  else
  {
    if (ecma_number_is_nan (date_num))
    {
      return ecma_make_number_value (date_num);
    }

    day_part = ecma_date_day (date_num);

    ecma_number_t hour = ecma_date_hour_from_time (date_num);
    ecma_number_t min = ecma_date_min_from_time (date_num);
    ecma_number_t sec = ecma_date_sec_from_time (date_num);
    ecma_number_t ms = ecma_date_ms_from_time (date_num);

    switch (builtin_routine_id)
    {
      case ECMA_DATE_PROTOTYPE_SET_HOURS:
      case ECMA_DATE_PROTOTYPE_SET_UTC_HOURS:
      {
        hour = converted_number[0];
        if (conversions >= 2)
        {
          min = converted_number[1];
        }
        if (conversions >= 3)
        {
          sec = converted_number[2];
        }
        if (conversions >= 4)
        {
          ms = converted_number[3];
        }
        break;
      }
      case ECMA_DATE_PROTOTYPE_SET_MINUTES:
      case ECMA_DATE_PROTOTYPE_SET_UTC_MINUTES:
      {
        min = converted_number[0];
        if (conversions >= 2)
        {
          sec = converted_number[1];
        }
        if (conversions >= 3)
        {
          ms = converted_number[2];
        }
        break;
      }
      case ECMA_DATE_PROTOTYPE_SET_UTC_SECONDS:
      case ECMA_DATE_PROTOTYPE_SET_SECONDS:
      {
        sec = converted_number[0];
        if (conversions >= 2)
        {
          ms = converted_number[1];
        }
        break;
      }
      default:
      {
        JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_UTC_MILLISECONDS
                      || builtin_routine_id == ECMA_DATE_PROTOTYPE_SET_MILLISECONDS);
        ms = converted_number[0];
        break;
      }
    }

    time_part = ecma_date_make_time (hour, min, sec, ms);
  }

  bool is_utc = BUILTIN_DATE_FUNCTION_IS_UTC (builtin_routine_id);

  ecma_number_t full_date = ecma_date_make_date (day_part, time_part);

  if (!is_utc)
  {
    full_date = ecma_date_utc (full_date);
  }

  full_date = ecma_date_time_clip (full_date);

  *ECMA_GET_INTERNAL_VALUE_POINTER (ecma_number_t, ext_object_p->u.class_prop.u.value) = full_date;

  return ecma_make_number_value (full_date);
} /* ecma_builtin_date_prototype_dispatch_set */
/**
 * Dispatch get date functions
 *
 * @return ecma value
 *         Returned value must be freed with ecma_free_value.
 */
static ecma_value_t
ecma_builtin_date_prototype_dispatch_get (uint16_t builtin_routine_id, /**< built-in wide routine
                                                                        *   identifier */
                                          ecma_number_t date_num) /**< date converted to number */
{
  if (ecma_number_is_nan (date_num))
  {
    return ecma_make_magic_string_value (LIT_MAGIC_STRING_NAN);
  }

  switch (builtin_routine_id)
  {
    case ECMA_DATE_PROTOTYPE_GET_FULL_YEAR:
    case ECMA_DATE_PROTOTYPE_GET_UTC_FULL_YEAR:
#ifndef CONFIG_DISABLE_ANNEXB_BUILTIN
    case ECMA_DATE_PROTOTYPE_GET_YEAR:
#endif /* !CONFIG_DISABLE_ANNEXB_BUILTIN */
    {
      date_num = ecma_date_year_from_time (date_num);

#ifndef CONFIG_DISABLE_ANNEXB_BUILTIN
      if (builtin_routine_id == ECMA_DATE_PROTOTYPE_GET_YEAR)
      {
        date_num -= 1900;
      }
#endif /* !CONFIG_DISABLE_ANNEXB_BUILTIN */

      break;
    }
    case ECMA_DATE_PROTOTYPE_GET_MONTH:
    case ECMA_DATE_PROTOTYPE_GET_UTC_MONTH:
    {
      date_num = ecma_date_month_from_time (date_num);
      break;
    }
    case ECMA_DATE_PROTOTYPE_GET_DATE:
    case ECMA_DATE_PROTOTYPE_GET_UTC_DATE:
    {
      date_num = ecma_date_date_from_time (date_num);
      break;
    }
    case ECMA_DATE_PROTOTYPE_GET_DAY:
    case ECMA_DATE_PROTOTYPE_GET_UTC_DAY:
    {
      date_num = ecma_date_week_day (date_num);
      break;
    }
    case ECMA_DATE_PROTOTYPE_GET_HOURS:
    case ECMA_DATE_PROTOTYPE_GET_UTC_HOURS:
    {
      date_num = ecma_date_hour_from_time (date_num);
      break;
    }
    case ECMA_DATE_PROTOTYPE_GET_MINUTES:
    case ECMA_DATE_PROTOTYPE_GET_UTC_MINUTES:
    {
      date_num = ecma_date_min_from_time (date_num);
      break;
    }
    case ECMA_DATE_PROTOTYPE_GET_SECONDS:
    case ECMA_DATE_PROTOTYPE_GET_UTC_SECONDS:
    {
      date_num = ecma_date_sec_from_time (date_num);
      break;
    }
    case ECMA_DATE_PROTOTYPE_GET_MILLISECONDS:
    case ECMA_DATE_PROTOTYPE_GET_UTC_MILLISECONDS:
    {
      date_num = ecma_date_ms_from_time (date_num);
      break;
    }
    default:
    {
      JERRY_ASSERT (builtin_routine_id == ECMA_DATE_PROTOTYPE_GET_UTC_TIMEZONE_OFFSET);
      date_num = ecma_date_timezone_offset (date_num);
      break;
    }
  }

  return ecma_make_number_value (date_num);
} /* ecma_builtin_date_prototype_dispatch_get */
/**
 * 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 char *day_names_p[8] =
  {
    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  };

  const char *month_names_p[13] =
  {
    "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  };

  const uint32_t date_buffer_length = 34;
  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 = (int32_t) ecma_date_year_from_time (datetime_number);
        number_length = 4;
        break;
      }
      case LIT_CHAR_UPPERCASE_M: /* Month. */
      {
        int32_t month = (int32_t) 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 = ((int32_t) ecma_date_month_from_time (datetime_number)) + 1;
        number_length = 2;
        break;
      }
      case LIT_CHAR_UPPERCASE_D: /* Day. */
      {
        number = (int32_t) ecma_date_date_from_time (datetime_number);
        number_length = 2;
        break;
      }
      case LIT_CHAR_UPPERCASE_W: /* Day of week. */
      {
        int32_t day = (int32_t) 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 = (int32_t) ecma_date_hour_from_time (datetime_number);
        number_length = 2;
        break;
      }
      case LIT_CHAR_LOWERCASE_M: /* Minutes. */
      {
        number = (int32_t) ecma_date_min_from_time (datetime_number);
        number_length = 2;
        break;
      }
      case LIT_CHAR_LOWERCASE_S: /* Seconds. */
      {
        number = (int32_t) ecma_date_sec_from_time (datetime_number);
        number_length = 2;
        break;
      }
      case LIT_CHAR_LOWERCASE_I: /* Milliseconds. */
      {
        number = (int32_t) ecma_date_ms_from_time (datetime_number);
        number_length = 3;
        break;
      }
      case LIT_CHAR_LOWERCASE_Z: /* Time zone minutes part. */
      {
        int32_t time_zone = (int32_t) ecma_date_local_time_zone (datetime_number);

        if (time_zone >= 0)
        {
          *dest_p++ = LIT_CHAR_PLUS;
        }
        else
        {
          *dest_p++ = LIT_CHAR_MINUS;
          time_zone = -time_zone;
        }

        number = time_zone / (int32_t) ECMA_DATE_MS_PER_HOUR;
        number_length = 2;
        break;
      }
      case LIT_CHAR_UPPERCASE_Z: /* Time zone seconds part. */
      {
        int32_t time_zone = (int32_t) ecma_date_local_time_zone (datetime_number);

        if (time_zone < 0)
        {
          time_zone = -time_zone;
        }

        number = time_zone % (int32_t) ECMA_DATE_MS_PER_HOUR;
        number_length = 2;
        break;
      }
      default:
      {
        JERRY_UNREACHABLE ();
        break;
      }
    }

    format_p++;

    if (str_p != NULL)
    {
      /* Print string values. */
      do
      {
        *dest_p++ = (lit_utf8_byte_t) *str_p++;
      }
      while (*str_p != LIT_CHAR_NULL);

      continue;
    }

    /* Print right aligned number values. */
    JERRY_ASSERT (number_length > 0);

    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 */