14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/js_date.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include <ctime>
194514f5e3Sopenharmony_ci#include <regex>
204514f5e3Sopenharmony_ci#include <sys/time.h>
214514f5e3Sopenharmony_ci
224514f5e3Sopenharmony_ci#include "ecmascript/date_parse.h"
234514f5e3Sopenharmony_ci#include "ecmascript/object_fast_operator-inl.h"
244514f5e3Sopenharmony_ci#include "ecmascript/platform/time.h"
254514f5e3Sopenharmony_ci
264514f5e3Sopenharmony_cinamespace panda::ecmascript {
274514f5e3Sopenharmony_ciusing NumberHelper = base::NumberHelper;
284514f5e3Sopenharmony_cibool DateUtils::isCached_ = false;
294514f5e3Sopenharmony_ciint DateUtils::preSumDays_ = 0;
304514f5e3Sopenharmony_ciint DateUtils::preDays_ = 0;
314514f5e3Sopenharmony_ciint DateUtils::preMonth_ = 0;
324514f5e3Sopenharmony_ciint DateUtils::preYear_ = 0;
334514f5e3Sopenharmony_cistatic const std::array<CString, WEEKDAY> WEEK_DAY_NAME = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
344514f5e3Sopenharmony_cistatic const std::array<CString, MOUTH_PER_YEAR> MONTH_NAME  = {
354514f5e3Sopenharmony_ci    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
364514f5e3Sopenharmony_ci    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
374514f5e3Sopenharmony_ci};
384514f5e3Sopenharmony_civoid DateUtils::TransferTimeToDate(int64_t timeMs, std::array<int64_t, DATE_LENGTH> *date)
394514f5e3Sopenharmony_ci{
404514f5e3Sopenharmony_ci    (*date)[HOUR] = Mod(timeMs, MS_PER_DAY);                                 // ms from hour, minutes, second, ms
414514f5e3Sopenharmony_ci    (*date)[DAYS] = (timeMs - (*date)[HOUR]) / MS_PER_DAY;                   // days from year, month, day
424514f5e3Sopenharmony_ci    (*date)[MS] = (*date)[HOUR] % MS_PER_SECOND;                             // ms
434514f5e3Sopenharmony_ci    (*date)[HOUR] = ((*date)[HOUR] - (*date)[MS]) / MS_PER_SECOND;           // s from hour, minutes, second
444514f5e3Sopenharmony_ci    (*date)[SEC] = (*date)[HOUR] % SEC_PER_MINUTE;                           // second
454514f5e3Sopenharmony_ci    (*date)[HOUR] = ((*date)[HOUR] - (*date)[SEC]) / SEC_PER_MINUTE;         // min from hour, minutes
464514f5e3Sopenharmony_ci    (*date)[MIN] = (*date)[HOUR] % SEC_PER_MINUTE;                           // min
474514f5e3Sopenharmony_ci    (*date)[HOUR] = ((*date)[HOUR] - (*date)[MIN]) / SEC_PER_MINUTE;         // hour
484514f5e3Sopenharmony_ci    (*date)[WEEKDAY] = Mod(((*date)[DAYS] + LEAP_NUMBER[0]), DAY_PER_WEEK);  // weekday
494514f5e3Sopenharmony_ci    GetYearFromDays(date);
504514f5e3Sopenharmony_ci}
514514f5e3Sopenharmony_ci// static
524514f5e3Sopenharmony_cibool DateUtils::IsLeap(int64_t year)
534514f5e3Sopenharmony_ci{
544514f5e3Sopenharmony_ci    return year % LEAP_NUMBER[0] == 0 && (year % LEAP_NUMBER[1] != 0 || year % LEAP_NUMBER[2] == 0);  // 2: means index
554514f5e3Sopenharmony_ci}
564514f5e3Sopenharmony_ci
574514f5e3Sopenharmony_ci// static
584514f5e3Sopenharmony_ciint64_t DateUtils::GetDaysInYear(int64_t year)
594514f5e3Sopenharmony_ci{
604514f5e3Sopenharmony_ci    int64_t number;
614514f5e3Sopenharmony_ci    number = IsLeap(year) ? (DAYS_IN_YEAR + 1) : DAYS_IN_YEAR;
624514f5e3Sopenharmony_ci    return number;
634514f5e3Sopenharmony_ci}
644514f5e3Sopenharmony_ci
654514f5e3Sopenharmony_ci// static
664514f5e3Sopenharmony_ciint64_t DateUtils::GetDaysFromYear(int64_t year)
674514f5e3Sopenharmony_ci{
684514f5e3Sopenharmony_ci    return DAYS_IN_YEAR * (year - YEAR_NUMBER[0]) + FloorDiv(year - YEAR_NUMBER[1], LEAP_NUMBER[0]) -
694514f5e3Sopenharmony_ci           FloorDiv(year - YEAR_NUMBER[2], LEAP_NUMBER[1]) +  // 2: year index
704514f5e3Sopenharmony_ci           FloorDiv(year - YEAR_NUMBER[3], LEAP_NUMBER[2]);   // 3, 2: year index
714514f5e3Sopenharmony_ci}
724514f5e3Sopenharmony_ci
734514f5e3Sopenharmony_ci// static
744514f5e3Sopenharmony_ciint64_t DateUtils::FloorDiv(int64_t a, int64_t b)
754514f5e3Sopenharmony_ci{
764514f5e3Sopenharmony_ci    ASSERT(b != 0);
774514f5e3Sopenharmony_ci    int64_t m = a % b;
784514f5e3Sopenharmony_ci    int64_t res = m < 0 ? ((a - m - b) / b) : ((a - m) / b);
794514f5e3Sopenharmony_ci    return res;
804514f5e3Sopenharmony_ci}
814514f5e3Sopenharmony_ci
824514f5e3Sopenharmony_ci// static
834514f5e3Sopenharmony_civoid DateUtils::GetYearFromDays(std::array<int64_t, DATE_LENGTH> *date)
844514f5e3Sopenharmony_ci{
854514f5e3Sopenharmony_ci    if (date == nullptr) {
864514f5e3Sopenharmony_ci        return;
874514f5e3Sopenharmony_ci    }
884514f5e3Sopenharmony_ci    if (isCached_) {
894514f5e3Sopenharmony_ci        int64_t t = (*date)[DAYS];
904514f5e3Sopenharmony_ci        int64_t newDays = preDays_ + (t - preSumDays_);
914514f5e3Sopenharmony_ci        if (newDays >= 1 && newDays < DAYS_FEBRUARY) {
924514f5e3Sopenharmony_ci            preSumDays_ = t;
934514f5e3Sopenharmony_ci            preDays_ = newDays;
944514f5e3Sopenharmony_ci            (*date)[DAYS] = newDays;
954514f5e3Sopenharmony_ci            (*date)[MONTH] = preMonth_;
964514f5e3Sopenharmony_ci            (*date)[YEAR] = preYear_;
974514f5e3Sopenharmony_ci            return;
984514f5e3Sopenharmony_ci        }
994514f5e3Sopenharmony_ci    }
1004514f5e3Sopenharmony_ci    int64_t realDay;
1014514f5e3Sopenharmony_ci    int64_t d = (*date)[DAYS];
1024514f5e3Sopenharmony_ci    preSumDays_ = d;
1034514f5e3Sopenharmony_ci    d += DAYS_1970_TO_0000;                                               // shift from 1970-01-01 to 0000-03-01
1044514f5e3Sopenharmony_ci    int64_t era = (d >= 0 ? d : d - DAYS_IN_400_YEARS + 1) / DAYS_IN_400_YEARS;   // an era is a 400 year period
1054514f5e3Sopenharmony_ci    int64_t doe = static_cast<int64_t>(d - era * DAYS_IN_400_YEARS);              // days of era
1064514f5e3Sopenharmony_ci    int64_t yoe = (doe - doe / DAYS_IN_4_YEARS + doe / DAYS_IN_100_YEARS -
1074514f5e3Sopenharmony_ci                   doe / (DAYS_IN_400_YEARS - 1)) / DAYS_IN_YEAR;                 // year of era
1084514f5e3Sopenharmony_ci    int64_t y = static_cast<int64_t>(yoe) + era * LEAP_NUMBER[2];
1094514f5e3Sopenharmony_ci    int64_t doy = doe - (DAYS_IN_YEAR * yoe + yoe / LEAP_NUMBER[0] -
1104514f5e3Sopenharmony_ci                  yoe / LEAP_NUMBER[1]);                                          // days of year
1114514f5e3Sopenharmony_ci    int64_t mp = (COEFFICIENT_TO_CIVIL[0] * doy + MONTH_COEFFICIENT) /
1124514f5e3Sopenharmony_ci                  COEFFICIENT_TO_CIVIL[1];                                        // [0, 11] / [Mar,Feb] system
1134514f5e3Sopenharmony_ci    int64_t month = mp + (mp < MONTH_TRANSFORM[1] ?
1144514f5e3Sopenharmony_ci                MONTH_TRANSFORM[0] : MONTH_TRANSFORM[2]);                         // transform month to civil system
1154514f5e3Sopenharmony_ci    int64_t year = y + (month <= MONTH_COEFFICIENT);
1164514f5e3Sopenharmony_ci    month -= 1;
1174514f5e3Sopenharmony_ci    realDay = doy - (COEFFICIENT_TO_CIVIL[1] * mp + 2) / COEFFICIENT_TO_CIVIL[0] + 1;   // 2: shift from 03-01 to 01-01
1184514f5e3Sopenharmony_ci    (*date)[YEAR] = year;
1194514f5e3Sopenharmony_ci    (*date)[MONTH] = month;
1204514f5e3Sopenharmony_ci    (*date)[DAYS] = realDay;
1214514f5e3Sopenharmony_ci    preDays_ = realDay;
1224514f5e3Sopenharmony_ci    preMonth_ = month;
1234514f5e3Sopenharmony_ci    preYear_ = year;
1244514f5e3Sopenharmony_ci    isCached_ = true;
1254514f5e3Sopenharmony_ci}
1264514f5e3Sopenharmony_ci
1274514f5e3Sopenharmony_ci// static
1284514f5e3Sopenharmony_ciint64_t DateUtils::Mod(int64_t a, int b)
1294514f5e3Sopenharmony_ci{
1304514f5e3Sopenharmony_ci    ASSERT(b != 0);
1314514f5e3Sopenharmony_ci    int64_t m = a % b;
1324514f5e3Sopenharmony_ci    int64_t res = m < 0 ? (m + b) : m;
1334514f5e3Sopenharmony_ci    return res;
1344514f5e3Sopenharmony_ci}
1354514f5e3Sopenharmony_ci
1364514f5e3Sopenharmony_ci// static
1374514f5e3Sopenharmony_ci// 20.4.1.11
1384514f5e3Sopenharmony_cidouble JSDate::MakeTime(double hour, double min, double sec, double ms)
1394514f5e3Sopenharmony_ci{
1404514f5e3Sopenharmony_ci    if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) && std::isfinite(ms)) {
1414514f5e3Sopenharmony_ci        double hourInteger = NumberHelper::TruncateDouble(hour);
1424514f5e3Sopenharmony_ci        double minInteger = NumberHelper::TruncateDouble(min);
1434514f5e3Sopenharmony_ci        double secInteger = NumberHelper::TruncateDouble(sec);
1444514f5e3Sopenharmony_ci        double msInteger = NumberHelper::TruncateDouble(ms);
1454514f5e3Sopenharmony_ci        return hourInteger * MS_PER_HOUR + minInteger * MS_PER_MINUTE + secInteger * MS_PER_SECOND + msInteger;
1464514f5e3Sopenharmony_ci    }
1474514f5e3Sopenharmony_ci    return base::NAN_VALUE;
1484514f5e3Sopenharmony_ci}
1494514f5e3Sopenharmony_ci
1504514f5e3Sopenharmony_ci// static
1514514f5e3Sopenharmony_ci// 20.4.1.12
1524514f5e3Sopenharmony_cidouble JSDate::MakeDay(double year, double month, double date)
1534514f5e3Sopenharmony_ci{
1544514f5e3Sopenharmony_ci    if (std::isfinite(year) && std::isfinite(month) && std::isfinite(date)) {
1554514f5e3Sopenharmony_ci        double yearInteger = NumberHelper::TruncateDouble(year);
1564514f5e3Sopenharmony_ci        double monthInteger = NumberHelper::TruncateDouble(month);
1574514f5e3Sopenharmony_ci        int64_t y = static_cast<int64_t>(yearInteger) + static_cast<int64_t>(monthInteger / MOUTH_PER_YEAR);
1584514f5e3Sopenharmony_ci        int64_t m = static_cast<int64_t>(monthInteger) % MOUTH_PER_YEAR;
1594514f5e3Sopenharmony_ci        if (m < 0) {
1604514f5e3Sopenharmony_ci            m += MOUTH_PER_YEAR;
1614514f5e3Sopenharmony_ci            y -= 1;
1624514f5e3Sopenharmony_ci        }
1634514f5e3Sopenharmony_ci
1644514f5e3Sopenharmony_ci        int64_t days = DateUtils::GetDaysFromYear(y);
1654514f5e3Sopenharmony_ci        int index = DateUtils::IsLeap(year) ? 1 : 0;
1664514f5e3Sopenharmony_ci        days += DAYS_FROM_MONTH[index][m];
1674514f5e3Sopenharmony_ci        return static_cast<double>(days - 1) + NumberHelper::TruncateDouble(date);
1684514f5e3Sopenharmony_ci    }
1694514f5e3Sopenharmony_ci    return base::NAN_VALUE;
1704514f5e3Sopenharmony_ci}
1714514f5e3Sopenharmony_ci
1724514f5e3Sopenharmony_ci// static
1734514f5e3Sopenharmony_ci// 20.4.1.13
1744514f5e3Sopenharmony_cidouble JSDate::MakeDate(double day, double time)
1754514f5e3Sopenharmony_ci{
1764514f5e3Sopenharmony_ci    if (std::isfinite(day) && std::isfinite(time)) {
1774514f5e3Sopenharmony_ci        return time + day * MS_PER_DAY;
1784514f5e3Sopenharmony_ci    }
1794514f5e3Sopenharmony_ci    return base::NAN_VALUE;
1804514f5e3Sopenharmony_ci}
1814514f5e3Sopenharmony_ci
1824514f5e3Sopenharmony_ci// static
1834514f5e3Sopenharmony_ci// 20.4.1.14
1844514f5e3Sopenharmony_cidouble JSDate::TimeClip(double time)
1854514f5e3Sopenharmony_ci{
1864514f5e3Sopenharmony_ci    if (-MAX_TIME_IN_MS <= time && time <= MAX_TIME_IN_MS) {
1874514f5e3Sopenharmony_ci        return NumberHelper::TruncateDouble(time);
1884514f5e3Sopenharmony_ci    }
1894514f5e3Sopenharmony_ci    return base::NAN_VALUE;
1904514f5e3Sopenharmony_ci}
1914514f5e3Sopenharmony_ci
1924514f5e3Sopenharmony_ci// 20.4.1.8
1934514f5e3Sopenharmony_cidouble JSDate::LocalTime(double timeMs) const
1944514f5e3Sopenharmony_ci{
1954514f5e3Sopenharmony_ci    return timeMs + GetLocalOffsetFromOS(timeMs, true);
1964514f5e3Sopenharmony_ci}
1974514f5e3Sopenharmony_ci
1984514f5e3Sopenharmony_ci// 20.4.1.9
1994514f5e3Sopenharmony_cidouble JSDate::UTCTime(double timeMs) const
2004514f5e3Sopenharmony_ci{
2014514f5e3Sopenharmony_ci    return timeMs - GetLocalOffsetFromOS(timeMs, false);
2024514f5e3Sopenharmony_ci}
2034514f5e3Sopenharmony_ci
2044514f5e3Sopenharmony_ci// static
2054514f5e3Sopenharmony_ciint JSDate::GetSignedNumFromString(const CString &str, int len, int *index)
2064514f5e3Sopenharmony_ci{
2074514f5e3Sopenharmony_ci    int res = 0;
2084514f5e3Sopenharmony_ci    GetNumFromString(str, len, index, &res);
2094514f5e3Sopenharmony_ci    if (str.at(0) == NEG) {
2104514f5e3Sopenharmony_ci        return -res;
2114514f5e3Sopenharmony_ci    }
2124514f5e3Sopenharmony_ci    return res;
2134514f5e3Sopenharmony_ci}
2144514f5e3Sopenharmony_ci
2154514f5e3Sopenharmony_ci// static
2164514f5e3Sopenharmony_cibool JSDate::GetNumFromString(const CString &str, int len, int *index, int *num)
2174514f5e3Sopenharmony_ci{
2184514f5e3Sopenharmony_ci    int indexStr = *index;
2194514f5e3Sopenharmony_ci    char oneByte = 0;
2204514f5e3Sopenharmony_ci    while (indexStr < len) {
2214514f5e3Sopenharmony_ci        oneByte = str.at(indexStr);
2224514f5e3Sopenharmony_ci        if (oneByte >= '0' && oneByte <= '9') {
2234514f5e3Sopenharmony_ci            break;
2244514f5e3Sopenharmony_ci        }
2254514f5e3Sopenharmony_ci        indexStr++;
2264514f5e3Sopenharmony_ci    }
2274514f5e3Sopenharmony_ci    if (indexStr >= len) {
2284514f5e3Sopenharmony_ci        return false;
2294514f5e3Sopenharmony_ci    }
2304514f5e3Sopenharmony_ci    int value = 0;
2314514f5e3Sopenharmony_ci    while (indexStr < len) {
2324514f5e3Sopenharmony_ci        oneByte = str.at(indexStr);
2334514f5e3Sopenharmony_ci        int val = static_cast<int>(oneByte - '0');
2344514f5e3Sopenharmony_ci        if (val >= 0 && val <= NUM_NINE) {
2354514f5e3Sopenharmony_ci            value = value * TEN + val;
2364514f5e3Sopenharmony_ci            indexStr++;
2374514f5e3Sopenharmony_ci        } else {
2384514f5e3Sopenharmony_ci            break;
2394514f5e3Sopenharmony_ci        }
2404514f5e3Sopenharmony_ci    }
2414514f5e3Sopenharmony_ci    *num = value;
2424514f5e3Sopenharmony_ci    *index = indexStr;
2434514f5e3Sopenharmony_ci    return true;
2444514f5e3Sopenharmony_ci}
2454514f5e3Sopenharmony_ci
2464514f5e3Sopenharmony_ci// 20.4.1.7
2474514f5e3Sopenharmony_ciint64_t JSDate::GetLocalOffsetInMin(const JSThread *thread, int64_t timeMs, bool isLocal)
2484514f5e3Sopenharmony_ci{
2494514f5e3Sopenharmony_ci    if (!isLocal) {
2504514f5e3Sopenharmony_ci        return 0;
2514514f5e3Sopenharmony_ci    }
2524514f5e3Sopenharmony_ci    double localOffset = this->GetLocalOffset().GetDouble();
2534514f5e3Sopenharmony_ci    if (localOffset == MAX_DOUBLE) {
2544514f5e3Sopenharmony_ci        localOffset = static_cast<double>(GetLocalOffsetFromOS(timeMs, isLocal));
2554514f5e3Sopenharmony_ci        SetLocalOffset(thread, JSTaggedValue(localOffset));
2564514f5e3Sopenharmony_ci    }
2574514f5e3Sopenharmony_ci    return localOffset;
2584514f5e3Sopenharmony_ci}
2594514f5e3Sopenharmony_ci
2604514f5e3Sopenharmony_ci// static
2614514f5e3Sopenharmony_ciJSTaggedValue JSDate::LocalParseStringToMs(const CString &str)
2624514f5e3Sopenharmony_ci{
2634514f5e3Sopenharmony_ci    int year = 0;
2644514f5e3Sopenharmony_ci    int month = 0;
2654514f5e3Sopenharmony_ci    int date = 1;
2664514f5e3Sopenharmony_ci    int hours = 0;
2674514f5e3Sopenharmony_ci    int minutes = 0;
2684514f5e3Sopenharmony_ci    int seconds = 0;
2694514f5e3Sopenharmony_ci    int ms = 0;
2704514f5e3Sopenharmony_ci    int index = 0;
2714514f5e3Sopenharmony_ci    int len = static_cast<int>(str.length());
2724514f5e3Sopenharmony_ci    bool isLocal = false;
2734514f5e3Sopenharmony_ci    CString::size_type indexGmt;
2744514f5e3Sopenharmony_ci    CString::size_type indexPlus = CString::npos;
2754514f5e3Sopenharmony_ci    int localTime = 0;
2764514f5e3Sopenharmony_ci    int localHours = 0;
2774514f5e3Sopenharmony_ci    int localMinutes = 0;
2784514f5e3Sopenharmony_ci    int64_t localMs = 0;
2794514f5e3Sopenharmony_ci    CString::size_type localSpace;
2804514f5e3Sopenharmony_ci    localSpace = str.find(' ', index);
2814514f5e3Sopenharmony_ci    CString strMonth = str.substr(localSpace + 1, LENGTH_MONTH_NAME);
2824514f5e3Sopenharmony_ci    for (int i = 0; i < MOUTH_PER_YEAR; i++) {
2834514f5e3Sopenharmony_ci        if (strMonth == MONTH_NAME[i]) {
2844514f5e3Sopenharmony_ci            month = i;
2854514f5e3Sopenharmony_ci            break;
2864514f5e3Sopenharmony_ci        }
2874514f5e3Sopenharmony_ci    }
2884514f5e3Sopenharmony_ci    index += (LENGTH_MONTH_NAME + 1);
2894514f5e3Sopenharmony_ci    GetNumFromString(str, len, &index, &date);
2904514f5e3Sopenharmony_ci    GetNumFromString(str, len, &index, &year);
2914514f5e3Sopenharmony_ci    indexGmt = str.find("GMT", index);
2924514f5e3Sopenharmony_ci    if (indexGmt == CString::npos) {
2934514f5e3Sopenharmony_ci        GetNumFromString(str, len, &index, &hours);
2944514f5e3Sopenharmony_ci        GetNumFromString(str, len, &index, &minutes);
2954514f5e3Sopenharmony_ci        GetNumFromString(str, len, &index, &seconds);
2964514f5e3Sopenharmony_ci        isLocal = true;
2974514f5e3Sopenharmony_ci        localMs -= (GetLocalOffsetFromOS(localMs, true) * MS_PER_MINUTE);
2984514f5e3Sopenharmony_ci    } else {
2994514f5e3Sopenharmony_ci        indexPlus = str.find(PLUS, indexGmt);
3004514f5e3Sopenharmony_ci        int indexLocal = static_cast<int>(indexGmt);
3014514f5e3Sopenharmony_ci        GetNumFromString(str, indexGmt, &index, &hours);
3024514f5e3Sopenharmony_ci        GetNumFromString(str, indexGmt, &index, &minutes);
3034514f5e3Sopenharmony_ci        GetNumFromString(str, indexGmt, &index, &seconds);
3044514f5e3Sopenharmony_ci        GetNumFromString(str, len, &indexLocal, &localTime);
3054514f5e3Sopenharmony_ci        localHours = localTime / HUNDRED;
3064514f5e3Sopenharmony_ci        localMinutes = localTime % HUNDRED;
3074514f5e3Sopenharmony_ci        localMs = static_cast<int64_t>(MakeTime(localHours, localMinutes, 0, 0));
3084514f5e3Sopenharmony_ci        if (indexPlus != CString::npos) {
3094514f5e3Sopenharmony_ci            localMs = -localMs;
3104514f5e3Sopenharmony_ci        }
3114514f5e3Sopenharmony_ci    }
3124514f5e3Sopenharmony_ci    double day = MakeDay(year, month, date);
3134514f5e3Sopenharmony_ci    double time = MakeTime(hours, minutes, seconds, ms);
3144514f5e3Sopenharmony_ci    double timeValue = TimeClip(MakeDate(day, time));
3154514f5e3Sopenharmony_ci    if (std::isnan(timeValue)) {
3164514f5e3Sopenharmony_ci        return JSTaggedValue(timeValue);
3174514f5e3Sopenharmony_ci    }
3184514f5e3Sopenharmony_ci    if (isLocal && timeValue < CHINA_1901_MS && (-localMs / MS_PER_MINUTE) == CHINA_AFTER_1901_MIN) {
3194514f5e3Sopenharmony_ci        timeValue += static_cast<double>(localMs - CHINA_BEFORE_1901_MS);
3204514f5e3Sopenharmony_ci    } else {
3214514f5e3Sopenharmony_ci        timeValue += localMs;
3224514f5e3Sopenharmony_ci    }
3234514f5e3Sopenharmony_ci    return JSTaggedValue(timeValue);
3244514f5e3Sopenharmony_ci}
3254514f5e3Sopenharmony_ci
3264514f5e3Sopenharmony_ci// static
3274514f5e3Sopenharmony_ciJSTaggedValue JSDate::UtcParseStringToMs(const CString &str)
3284514f5e3Sopenharmony_ci{
3294514f5e3Sopenharmony_ci    int year = 0;
3304514f5e3Sopenharmony_ci    int month = 0;
3314514f5e3Sopenharmony_ci    int date = 1;
3324514f5e3Sopenharmony_ci    int hours = 0;
3334514f5e3Sopenharmony_ci    int minutes = 0;
3344514f5e3Sopenharmony_ci    int seconds = 0;
3354514f5e3Sopenharmony_ci    int ms = 0;
3364514f5e3Sopenharmony_ci    int index = 0;
3374514f5e3Sopenharmony_ci    int len = static_cast<int>(str.length());
3384514f5e3Sopenharmony_ci    CString::size_type indexGmt;
3394514f5e3Sopenharmony_ci    CString::size_type indexPlus = CString::npos;
3404514f5e3Sopenharmony_ci    int localTime = 0;
3414514f5e3Sopenharmony_ci    int localHours = 0;
3424514f5e3Sopenharmony_ci    int localMinutes = 0;
3434514f5e3Sopenharmony_ci    int64_t localMs = 0;
3444514f5e3Sopenharmony_ci    bool isLocal = false;
3454514f5e3Sopenharmony_ci    GetNumFromString(str, len, &index, &date);
3464514f5e3Sopenharmony_ci    CString strMonth = str.substr(index + 1, LENGTH_MONTH_NAME);
3474514f5e3Sopenharmony_ci    for (int i = 0; i < MOUTH_PER_YEAR; i++) {
3484514f5e3Sopenharmony_ci        if (strMonth == MONTH_NAME[i]) {
3494514f5e3Sopenharmony_ci            month = i;
3504514f5e3Sopenharmony_ci            break;
3514514f5e3Sopenharmony_ci        }
3524514f5e3Sopenharmony_ci    }
3534514f5e3Sopenharmony_ci    index += (LENGTH_MONTH_NAME + 1);
3544514f5e3Sopenharmony_ci    GetNumFromString(str, len, &index, &year);
3554514f5e3Sopenharmony_ci    indexGmt = str.find("GMT", index);
3564514f5e3Sopenharmony_ci    if (indexGmt == CString::npos) {
3574514f5e3Sopenharmony_ci        GetNumFromString(str, len, &index, &hours);
3584514f5e3Sopenharmony_ci        GetNumFromString(str, len, &index, &minutes);
3594514f5e3Sopenharmony_ci        GetNumFromString(str, len, &index, &seconds);
3604514f5e3Sopenharmony_ci        isLocal = true;
3614514f5e3Sopenharmony_ci        localMs -= (GetLocalOffsetFromOS(localMs, true) * MS_PER_MINUTE);
3624514f5e3Sopenharmony_ci    } else {
3634514f5e3Sopenharmony_ci        indexPlus = str.find(PLUS, indexGmt);
3644514f5e3Sopenharmony_ci        int indexLocal = static_cast<int>(indexGmt);
3654514f5e3Sopenharmony_ci        GetNumFromString(str, indexGmt, &index, &hours);
3664514f5e3Sopenharmony_ci        GetNumFromString(str, indexGmt, &index, &minutes);
3674514f5e3Sopenharmony_ci        GetNumFromString(str, indexGmt, &index, &seconds);
3684514f5e3Sopenharmony_ci        GetNumFromString(str, len, &indexLocal, &localTime);
3694514f5e3Sopenharmony_ci        localHours = localTime / HUNDRED;
3704514f5e3Sopenharmony_ci        localMinutes = localTime % HUNDRED;
3714514f5e3Sopenharmony_ci        localMs = static_cast<int64_t>(MakeTime(localHours, localMinutes, 0, 0));
3724514f5e3Sopenharmony_ci        if (indexPlus != CString::npos) {
3734514f5e3Sopenharmony_ci            localMs = -localMs;
3744514f5e3Sopenharmony_ci        }
3754514f5e3Sopenharmony_ci    }
3764514f5e3Sopenharmony_ci    double day = MakeDay(year, month, date);
3774514f5e3Sopenharmony_ci    double time = MakeTime(hours, minutes, seconds, ms);
3784514f5e3Sopenharmony_ci    double timeValue = TimeClip(MakeDate(day, time));
3794514f5e3Sopenharmony_ci    if (std::isnan(timeValue)) {
3804514f5e3Sopenharmony_ci        return JSTaggedValue(timeValue);
3814514f5e3Sopenharmony_ci    }
3824514f5e3Sopenharmony_ci    if (isLocal && timeValue < CHINA_1901_MS && (-localMs / MS_PER_MINUTE) == CHINA_AFTER_1901_MIN) {
3834514f5e3Sopenharmony_ci        timeValue += static_cast<double>(localMs - CHINA_BEFORE_1901_MS);
3844514f5e3Sopenharmony_ci    } else {
3854514f5e3Sopenharmony_ci        timeValue += localMs;
3864514f5e3Sopenharmony_ci    }
3874514f5e3Sopenharmony_ci    return JSTaggedValue(timeValue);
3884514f5e3Sopenharmony_ci}
3894514f5e3Sopenharmony_ci// static
3904514f5e3Sopenharmony_ciJSTaggedValue JSDate::IsoParseStringToMs(const CString &str)
3914514f5e3Sopenharmony_ci{
3924514f5e3Sopenharmony_ci    char flag = 0;
3934514f5e3Sopenharmony_ci    int year;
3944514f5e3Sopenharmony_ci    int month = 1;
3954514f5e3Sopenharmony_ci    int date = 1;
3964514f5e3Sopenharmony_ci    int hours = 0;
3974514f5e3Sopenharmony_ci    int minutes = 0;
3984514f5e3Sopenharmony_ci    int seconds = 0;
3994514f5e3Sopenharmony_ci    int ms = 0;
4004514f5e3Sopenharmony_ci    int index = 0;
4014514f5e3Sopenharmony_ci    int len = static_cast<int>(str.length());
4024514f5e3Sopenharmony_ci    year = GetSignedNumFromString(str, len, &index);
4034514f5e3Sopenharmony_ci    CString::size_type indexT = str.find(FLAG_TIME, index);
4044514f5e3Sopenharmony_ci    CString::size_type indexZ = str.find(FLAG_UTC, index);
4054514f5e3Sopenharmony_ci    CString::size_type indexEndFlag = 0;
4064514f5e3Sopenharmony_ci    int64_t localMs = 0;
4074514f5e3Sopenharmony_ci    if (indexZ != CString::npos) {
4084514f5e3Sopenharmony_ci        indexEndFlag = indexZ;
4094514f5e3Sopenharmony_ci    } else if (len >= MIN_LENGTH && str.at(len - INDEX_PLUS_NEG) == NEG) {
4104514f5e3Sopenharmony_ci        indexEndFlag = static_cast<CString::size_type>(len - INDEX_PLUS_NEG);
4114514f5e3Sopenharmony_ci        flag = NEG;
4124514f5e3Sopenharmony_ci    } else if (len >= MIN_LENGTH && str.at(len - INDEX_PLUS_NEG) == PLUS) {
4134514f5e3Sopenharmony_ci        indexEndFlag = static_cast<CString::size_type>(len - INDEX_PLUS_NEG);
4144514f5e3Sopenharmony_ci        flag = PLUS;
4154514f5e3Sopenharmony_ci    }
4164514f5e3Sopenharmony_ci    if (indexT != CString::npos) {
4174514f5e3Sopenharmony_ci        if (static_cast<int>(indexT) - index == LENGTH_PER_TIME) {
4184514f5e3Sopenharmony_ci            GetNumFromString(str, len, &index, &month);
4194514f5e3Sopenharmony_ci        } else if (static_cast<int>(indexT) - index == (LENGTH_PER_TIME + LENGTH_PER_TIME)) {
4204514f5e3Sopenharmony_ci            GetNumFromString(str, len, &index, &month);
4214514f5e3Sopenharmony_ci            GetNumFromString(str, len, &index, &date);
4224514f5e3Sopenharmony_ci        }
4234514f5e3Sopenharmony_ci        GetNumFromString(str, len, &index, &hours);
4244514f5e3Sopenharmony_ci        GetNumFromString(str, len, &index, &minutes);
4254514f5e3Sopenharmony_ci        if (indexEndFlag > 0) {
4264514f5e3Sopenharmony_ci            if (static_cast<int>(indexEndFlag) - index == LENGTH_PER_TIME) {
4274514f5e3Sopenharmony_ci                GetNumFromString(str, len, &index, &seconds);
4284514f5e3Sopenharmony_ci            } else if (static_cast<int>(indexEndFlag) - index == (LENGTH_PER_TIME + LENGTH_PER_TIME + 1)) {
4294514f5e3Sopenharmony_ci                GetNumFromString(str, len, &index, &seconds);
4304514f5e3Sopenharmony_ci                GetNumFromString(str, len, &index, &ms);
4314514f5e3Sopenharmony_ci            }
4324514f5e3Sopenharmony_ci        } else {
4334514f5e3Sopenharmony_ci            if (len - index == LENGTH_PER_TIME) {
4344514f5e3Sopenharmony_ci                GetNumFromString(str, len, &index, &seconds);
4354514f5e3Sopenharmony_ci            } else if (len - index == (LENGTH_PER_TIME + LENGTH_PER_TIME + 1)) {
4364514f5e3Sopenharmony_ci                GetNumFromString(str, len, &index, &seconds);
4374514f5e3Sopenharmony_ci                GetNumFromString(str, len, &index, &ms);
4384514f5e3Sopenharmony_ci            }
4394514f5e3Sopenharmony_ci        }
4404514f5e3Sopenharmony_ci    } else {
4414514f5e3Sopenharmony_ci        GetNumFromString(str, len, &index, &month);
4424514f5e3Sopenharmony_ci        GetNumFromString(str, len, &index, &date);
4434514f5e3Sopenharmony_ci    }
4444514f5e3Sopenharmony_ci    if (indexEndFlag > 0) {
4454514f5e3Sopenharmony_ci        int localHours = 0;
4464514f5e3Sopenharmony_ci        int localMinutes = 0;
4474514f5e3Sopenharmony_ci        if (indexZ == CString::npos) {
4484514f5e3Sopenharmony_ci            GetNumFromString(str, len, &index, &localHours);
4494514f5e3Sopenharmony_ci            GetNumFromString(str, len, &index, &localMinutes);
4504514f5e3Sopenharmony_ci            if (flag == PLUS) {
4514514f5e3Sopenharmony_ci                localMs = static_cast<int64_t>(-MakeTime(localHours, localMinutes, 0, 0));
4524514f5e3Sopenharmony_ci            } else {
4534514f5e3Sopenharmony_ci                localMs = static_cast<int64_t>(MakeTime(localHours, localMinutes, 0, 0));
4544514f5e3Sopenharmony_ci            }
4554514f5e3Sopenharmony_ci        }
4564514f5e3Sopenharmony_ci    }
4574514f5e3Sopenharmony_ci    if (indexEndFlag == 0 && indexT != CString::npos) {
4584514f5e3Sopenharmony_ci        localMs -= (GetLocalOffsetFromOS(localMs, true) * MS_PER_MINUTE);
4594514f5e3Sopenharmony_ci    }
4604514f5e3Sopenharmony_ci
4614514f5e3Sopenharmony_ci    double day = MakeDay(year, month - 1, date);
4624514f5e3Sopenharmony_ci    double time = MakeTime(hours, minutes, seconds, ms);
4634514f5e3Sopenharmony_ci    double timeValue = TimeClip(MakeDate(day, time));
4644514f5e3Sopenharmony_ci    if (std::isnan(timeValue)) {
4654514f5e3Sopenharmony_ci        return JSTaggedValue(timeValue);
4664514f5e3Sopenharmony_ci    }
4674514f5e3Sopenharmony_ci    if (flag == 0 && timeValue < CHINA_1901_MS && (-localMs / MS_PER_MINUTE) == CHINA_AFTER_1901_MIN) {
4684514f5e3Sopenharmony_ci        timeValue += static_cast<double>(localMs - CHINA_BEFORE_1901_MS);
4694514f5e3Sopenharmony_ci    } else {
4704514f5e3Sopenharmony_ci        timeValue += localMs;
4714514f5e3Sopenharmony_ci    }
4724514f5e3Sopenharmony_ci    return JSTaggedValue(timeValue);
4734514f5e3Sopenharmony_ci}
4744514f5e3Sopenharmony_ci
4754514f5e3Sopenharmony_ciJSTaggedValue JSDate::GetTimeFromString(const char *str, int len)
4764514f5e3Sopenharmony_ci{
4774514f5e3Sopenharmony_ci    int time[TIMEZONE + 1];
4784514f5e3Sopenharmony_ci    bool res = DateParse::ParseDateString(str, len, time);
4794514f5e3Sopenharmony_ci    if (res) {
4804514f5e3Sopenharmony_ci        double day = MakeDay(time[YEAR], time[MONTH], time[DAYS]);
4814514f5e3Sopenharmony_ci        double dateTime = MakeTime(time[HOUR], time[MIN], time[SEC], time[MS]);
4824514f5e3Sopenharmony_ci        double timeValue = TimeClip(MakeDate(day, dateTime));
4834514f5e3Sopenharmony_ci        if (std::isnan(timeValue)) {
4844514f5e3Sopenharmony_ci            return JSTaggedValue(timeValue);
4854514f5e3Sopenharmony_ci        }
4864514f5e3Sopenharmony_ci        int64_t localMs;
4874514f5e3Sopenharmony_ci        if (time[TIMEZONE] == INT_MAX) {
4884514f5e3Sopenharmony_ci            localMs = GetLocalOffsetFromOS(static_cast<int64_t>(timeValue), true) * MS_PER_MINUTE;
4894514f5e3Sopenharmony_ci        } else {
4904514f5e3Sopenharmony_ci            localMs = time[TIMEZONE] * MS_PER_SECOND;
4914514f5e3Sopenharmony_ci        }
4924514f5e3Sopenharmony_ci        timeValue -= localMs;
4934514f5e3Sopenharmony_ci        return JSTaggedValue(timeValue);
4944514f5e3Sopenharmony_ci    }
4954514f5e3Sopenharmony_ci    return JSTaggedValue(base::NAN_VALUE);
4964514f5e3Sopenharmony_ci}
4974514f5e3Sopenharmony_ci
4984514f5e3Sopenharmony_ci// 20.4.3.2 static
4994514f5e3Sopenharmony_ciJSTaggedValue JSDate::Parse(EcmaRuntimeCallInfo *argv)
5004514f5e3Sopenharmony_ci{
5014514f5e3Sopenharmony_ci    ASSERT(argv);
5024514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
5034514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> msg = base::BuiltinsBase::GetCallArg(argv, 0);
5044514f5e3Sopenharmony_ci    JSHandle<EcmaString> ecmaStr = JSTaggedValue::ToString(thread, msg);
5054514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
5064514f5e3Sopenharmony_ci    CVector<uint8_t> tmpBuf;
5074514f5e3Sopenharmony_ci    EcmaStringAccessor strAccessor(const_cast<EcmaString *>(*ecmaStr));
5084514f5e3Sopenharmony_ci    if (strAccessor.IsUtf16()) {
5094514f5e3Sopenharmony_ci        return JSTaggedValue(base::NAN_VALUE);
5104514f5e3Sopenharmony_ci    }
5114514f5e3Sopenharmony_ci    int len = static_cast<int>(strAccessor.GetLength());
5124514f5e3Sopenharmony_ci    auto data = reinterpret_cast<const char *>(strAccessor.GetUtf8DataFlat(*ecmaStr, tmpBuf));
5134514f5e3Sopenharmony_ci    return GetTimeFromString(data, len);
5144514f5e3Sopenharmony_ci}
5154514f5e3Sopenharmony_ci
5164514f5e3Sopenharmony_ci// 20.4.3.1
5174514f5e3Sopenharmony_ciJSTaggedValue JSDate::Now()
5184514f5e3Sopenharmony_ci{
5194514f5e3Sopenharmony_ci    // time from now is in ms.
5204514f5e3Sopenharmony_ci    int64_t ans;
5214514f5e3Sopenharmony_ci    struct timeval tv {
5224514f5e3Sopenharmony_ci    };
5234514f5e3Sopenharmony_ci    gettimeofday(&tv, nullptr);
5244514f5e3Sopenharmony_ci    ans = static_cast<int64_t>(tv.tv_sec) * MS_PER_SECOND + (tv.tv_usec / MS_PER_SECOND);
5254514f5e3Sopenharmony_ci    return JSTaggedValue(static_cast<double>(ans));
5264514f5e3Sopenharmony_ci}
5274514f5e3Sopenharmony_ci
5284514f5e3Sopenharmony_ci// 20.4.4.2 static
5294514f5e3Sopenharmony_ciJSTaggedValue JSDate::UTC(EcmaRuntimeCallInfo *argv)
5304514f5e3Sopenharmony_ci{
5314514f5e3Sopenharmony_ci    double year = 0.0;
5324514f5e3Sopenharmony_ci    double month = 0.0;
5334514f5e3Sopenharmony_ci    double date = 1.0;
5344514f5e3Sopenharmony_ci    double hours = 0.0;
5354514f5e3Sopenharmony_ci    double minutes = 0.0;
5364514f5e3Sopenharmony_ci    double seconds = 0.0;
5374514f5e3Sopenharmony_ci    double ms = 0.0;
5384514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
5394514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> yearArg = base::BuiltinsBase::GetCallArg(argv, 0);
5404514f5e3Sopenharmony_ci    JSTaggedNumber yearValue = JSTaggedValue::ToNumber(thread, yearArg);
5414514f5e3Sopenharmony_ci    RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
5424514f5e3Sopenharmony_ci    if (yearValue.IsNumber()) {
5434514f5e3Sopenharmony_ci        year = yearValue.GetNumber();
5444514f5e3Sopenharmony_ci        if (std::isfinite(year) && !yearValue.IsInt()) {
5454514f5e3Sopenharmony_ci            year = NumberHelper::TruncateDouble(year);
5464514f5e3Sopenharmony_ci        }
5474514f5e3Sopenharmony_ci        if (year >= 0 && year <= (HUNDRED - 1)) {
5484514f5e3Sopenharmony_ci            year = year + NINETEEN_HUNDRED_YEAR;
5494514f5e3Sopenharmony_ci        }
5504514f5e3Sopenharmony_ci    } else {
5514514f5e3Sopenharmony_ci        year = base::NAN_VALUE;
5524514f5e3Sopenharmony_ci    }
5534514f5e3Sopenharmony_ci    uint32_t index = 1;
5544514f5e3Sopenharmony_ci    uint32_t numArgs = argv->GetArgsNumber();
5554514f5e3Sopenharmony_ci    JSTaggedValue res;
5564514f5e3Sopenharmony_ci    if (numArgs > index) {
5574514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> value = base::BuiltinsBase::GetCallArg(argv, index);
5584514f5e3Sopenharmony_ci        res = JSTaggedValue::ToNumber(thread, value);
5594514f5e3Sopenharmony_ci        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
5604514f5e3Sopenharmony_ci        month = res.GetNumber();
5614514f5e3Sopenharmony_ci        index++;
5624514f5e3Sopenharmony_ci    }
5634514f5e3Sopenharmony_ci    if (numArgs > index) {
5644514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> value = base::BuiltinsBase::GetCallArg(argv, index);
5654514f5e3Sopenharmony_ci        res = JSTaggedValue::ToNumber(thread, value);
5664514f5e3Sopenharmony_ci        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
5674514f5e3Sopenharmony_ci        date = res.GetNumber();
5684514f5e3Sopenharmony_ci        index++;
5694514f5e3Sopenharmony_ci    }
5704514f5e3Sopenharmony_ci    if (numArgs > index) {
5714514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> value = base::BuiltinsBase::GetCallArg(argv, index);
5724514f5e3Sopenharmony_ci        res = JSTaggedValue::ToNumber(thread, value);
5734514f5e3Sopenharmony_ci        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
5744514f5e3Sopenharmony_ci        hours = res.GetNumber();
5754514f5e3Sopenharmony_ci        index++;
5764514f5e3Sopenharmony_ci    }
5774514f5e3Sopenharmony_ci    if (numArgs > index) {
5784514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> value = base::BuiltinsBase::GetCallArg(argv, index);
5794514f5e3Sopenharmony_ci        res = JSTaggedValue::ToNumber(thread, value);
5804514f5e3Sopenharmony_ci        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
5814514f5e3Sopenharmony_ci        minutes = res.GetNumber();
5824514f5e3Sopenharmony_ci        index++;
5834514f5e3Sopenharmony_ci    }
5844514f5e3Sopenharmony_ci    if (numArgs > index) {
5854514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> value = base::BuiltinsBase::GetCallArg(argv, index);
5864514f5e3Sopenharmony_ci        res = JSTaggedValue::ToNumber(thread, value);
5874514f5e3Sopenharmony_ci        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
5884514f5e3Sopenharmony_ci        seconds = res.GetNumber();
5894514f5e3Sopenharmony_ci        index++;
5904514f5e3Sopenharmony_ci    }
5914514f5e3Sopenharmony_ci    if (numArgs > index) {
5924514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> value = base::BuiltinsBase::GetCallArg(argv, index);
5934514f5e3Sopenharmony_ci        res = JSTaggedValue::ToNumber(thread, value);
5944514f5e3Sopenharmony_ci        RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
5954514f5e3Sopenharmony_ci        ms = res.GetNumber();
5964514f5e3Sopenharmony_ci    }
5974514f5e3Sopenharmony_ci    double day = MakeDay(year, month, date);
5984514f5e3Sopenharmony_ci    double time = MakeTime(hours, minutes, seconds, ms);
5994514f5e3Sopenharmony_ci    return JSTaggedValue(TimeClip(MakeDate(day, time)));
6004514f5e3Sopenharmony_ci}
6014514f5e3Sopenharmony_ci
6024514f5e3Sopenharmony_ci// 20.4.4.10
6034514f5e3Sopenharmony_ciJSTaggedValue JSDate::GetTime() const
6044514f5e3Sopenharmony_ci{
6054514f5e3Sopenharmony_ci    return GetTimeValue();
6064514f5e3Sopenharmony_ci}
6074514f5e3Sopenharmony_ci
6084514f5e3Sopenharmony_ci// static
6094514f5e3Sopenharmony_ciCString JSDate::StrToTargetLength(const CString &str, int length)
6104514f5e3Sopenharmony_ci{
6114514f5e3Sopenharmony_ci    int len = 0;
6124514f5e3Sopenharmony_ci    CString sub;
6134514f5e3Sopenharmony_ci    if (str[0] == NEG) {
6144514f5e3Sopenharmony_ci        sub.reserve(length + 1);
6154514f5e3Sopenharmony_ci        ASSERT(str.length() > 0);
6164514f5e3Sopenharmony_ci        len = static_cast<int>(str.length() - 1);
6174514f5e3Sopenharmony_ci        sub += NEG;
6184514f5e3Sopenharmony_ci    } else {
6194514f5e3Sopenharmony_ci        sub.reserve(length);
6204514f5e3Sopenharmony_ci        len = static_cast<int>(str.length());
6214514f5e3Sopenharmony_ci    }
6224514f5e3Sopenharmony_ci    int dif = length - len;
6234514f5e3Sopenharmony_ci    for (int i = 0; i < dif; i++) {
6244514f5e3Sopenharmony_ci        sub += '0';
6254514f5e3Sopenharmony_ci    }
6264514f5e3Sopenharmony_ci    if (str[0] == NEG) {
6274514f5e3Sopenharmony_ci        sub += str.substr(1, len);
6284514f5e3Sopenharmony_ci    } else {
6294514f5e3Sopenharmony_ci        sub += str;
6304514f5e3Sopenharmony_ci    }
6314514f5e3Sopenharmony_ci    return sub;
6324514f5e3Sopenharmony_ci}
6334514f5e3Sopenharmony_ci
6344514f5e3Sopenharmony_ci// static
6354514f5e3Sopenharmony_civoid JSDate::AppendStrToTargetLength(const CString &str, int length, CString &target)
6364514f5e3Sopenharmony_ci{
6374514f5e3Sopenharmony_ci    int len = 0;
6384514f5e3Sopenharmony_ci    if (str[0] == NEG) {
6394514f5e3Sopenharmony_ci        len = static_cast<int>(str.length() - 1);
6404514f5e3Sopenharmony_ci        target += NEG;
6414514f5e3Sopenharmony_ci    } else {
6424514f5e3Sopenharmony_ci        len = static_cast<int>(str.length());
6434514f5e3Sopenharmony_ci    }
6444514f5e3Sopenharmony_ci    int dif = length - len;
6454514f5e3Sopenharmony_ci    for (int i = 0; i < dif; i++) {
6464514f5e3Sopenharmony_ci        target += '0';
6474514f5e3Sopenharmony_ci    }
6484514f5e3Sopenharmony_ci    if (str[0] == NEG) {
6494514f5e3Sopenharmony_ci        target += str.substr(1, len);
6504514f5e3Sopenharmony_ci    } else {
6514514f5e3Sopenharmony_ci        target += str;
6524514f5e3Sopenharmony_ci    }
6534514f5e3Sopenharmony_ci}
6544514f5e3Sopenharmony_ci
6554514f5e3Sopenharmony_cibool JSDate::GetThisDateValues(std::array<int64_t, DATE_LENGTH> *date, bool isLocal) const
6564514f5e3Sopenharmony_ci{
6574514f5e3Sopenharmony_ci    double timeMs = this->GetTimeValue().GetDouble();
6584514f5e3Sopenharmony_ci    if (std::isnan(timeMs)) {
6594514f5e3Sopenharmony_ci        return false;
6604514f5e3Sopenharmony_ci    }
6614514f5e3Sopenharmony_ci    GetDateValues(timeMs, date, isLocal);
6624514f5e3Sopenharmony_ci    return true;
6634514f5e3Sopenharmony_ci}
6644514f5e3Sopenharmony_ci
6654514f5e3Sopenharmony_ci// 20.4.4.35
6664514f5e3Sopenharmony_ciJSTaggedValue JSDate::ToDateString(JSThread *thread) const
6674514f5e3Sopenharmony_ci{
6684514f5e3Sopenharmony_ci    std::array<int64_t, DATE_LENGTH> fields = {0};
6694514f5e3Sopenharmony_ci    if (!GetThisDateValues(&fields, true)) {
6704514f5e3Sopenharmony_ci        return JSTaggedValue(base::NAN_VALUE);
6714514f5e3Sopenharmony_ci    }
6724514f5e3Sopenharmony_ci    CString str;
6734514f5e3Sopenharmony_ci    str.reserve(DATE_STRING_LENGTH);
6744514f5e3Sopenharmony_ci    str.append(WEEK_DAY_NAME[fields[WEEKDAY]]) // Append weekdy name
6754514f5e3Sopenharmony_ci        .append(SPACE_STR) // Append SPACE
6764514f5e3Sopenharmony_ci        .append(MONTH_NAME[fields[MONTH]]) // Append mouth name
6774514f5e3Sopenharmony_ci        .append(SPACE_STR); // Append SPACE
6784514f5e3Sopenharmony_ci    ConvertAndAppend(fields[DAYS], STR_LENGTH_OTHERS, str);
6794514f5e3Sopenharmony_ci    str += SPACE;
6804514f5e3Sopenharmony_ci    ConvertAndAppend(fields[YEAR], STR_LENGTH_YEAR, str);
6814514f5e3Sopenharmony_ci    JSHandle<EcmaString> result = thread->GetEcmaVM()->GetFactory()->NewFromASCII(str);
6824514f5e3Sopenharmony_ci    return result.GetTaggedValue();
6834514f5e3Sopenharmony_ci}
6844514f5e3Sopenharmony_ci
6854514f5e3Sopenharmony_ci// static
6864514f5e3Sopenharmony_ciCString JSDate::ToDateString(double timeMs)
6874514f5e3Sopenharmony_ci{
6884514f5e3Sopenharmony_ci    if (std::isnan(timeMs)) {
6894514f5e3Sopenharmony_ci        return "Invalid Date";
6904514f5e3Sopenharmony_ci    }
6914514f5e3Sopenharmony_ci    std::array<int64_t, DATE_LENGTH> fields = {0};
6924514f5e3Sopenharmony_ci    GetDateValues(timeMs, &fields, true);
6934514f5e3Sopenharmony_ci    CString localTime;
6944514f5e3Sopenharmony_ci    int localMin = 0;
6954514f5e3Sopenharmony_ci    localMin = GetLocalOffsetFromOS(timeMs, true);
6964514f5e3Sopenharmony_ci    if (localMin >= 0) {
6974514f5e3Sopenharmony_ci        localTime += PLUS;
6984514f5e3Sopenharmony_ci    } else {
6994514f5e3Sopenharmony_ci        localTime += NEG;
7004514f5e3Sopenharmony_ci        localMin = -localMin;
7014514f5e3Sopenharmony_ci    }
7024514f5e3Sopenharmony_ci    localTime = localTime + StrToTargetLength(ToCString(localMin / MINUTE_PER_HOUR), STR_LENGTH_OTHERS);
7034514f5e3Sopenharmony_ci    localTime = localTime + StrToTargetLength(ToCString(localMin % MINUTE_PER_HOUR), STR_LENGTH_OTHERS);
7044514f5e3Sopenharmony_ci    CString str;
7054514f5e3Sopenharmony_ci    str.reserve(DATE_CSTRING_LENGTH);
7064514f5e3Sopenharmony_ci    str.append(WEEK_DAY_NAME[fields[WEEKDAY]]) // Append weekday name
7074514f5e3Sopenharmony_ci        .append(SPACE_STR)  // Append SPACE
7084514f5e3Sopenharmony_ci        .append(MONTH_NAME[fields[MONTH]]) // Append mouth name
7094514f5e3Sopenharmony_ci        .append(SPACE_STR); // Append SPACE
7104514f5e3Sopenharmony_ci    ConvertAndAppend(fields[DAYS], STR_LENGTH_OTHERS, str);
7114514f5e3Sopenharmony_ci    str += SPACE;
7124514f5e3Sopenharmony_ci    ConvertAndAppend(fields[YEAR], STR_LENGTH_YEAR, str);
7134514f5e3Sopenharmony_ci    str += SPACE;
7144514f5e3Sopenharmony_ci    ConvertAndAppend(fields[HOUR], STR_LENGTH_OTHERS, str);
7154514f5e3Sopenharmony_ci    str += COLON;
7164514f5e3Sopenharmony_ci    ConvertAndAppend(fields[MIN], STR_LENGTH_OTHERS, str);
7174514f5e3Sopenharmony_ci    str += COLON;
7184514f5e3Sopenharmony_ci    ConvertAndAppend(fields[SEC], STR_LENGTH_OTHERS, str);
7194514f5e3Sopenharmony_ci    str.append(SPACE_STR) // Append SPACE
7204514f5e3Sopenharmony_ci        .append("GMT") // Append GMT
7214514f5e3Sopenharmony_ci        .append(localTime); // Append localTime
7224514f5e3Sopenharmony_ci    return str;
7234514f5e3Sopenharmony_ci}
7244514f5e3Sopenharmony_ci// 20.4.4.36
7254514f5e3Sopenharmony_ciJSTaggedValue JSDate::ToISOString(JSThread *thread) const
7264514f5e3Sopenharmony_ci{
7274514f5e3Sopenharmony_ci    std::array<int64_t, DATE_LENGTH> fields = {0};
7284514f5e3Sopenharmony_ci    if (!GetThisDateValues(&fields, false)) {
7294514f5e3Sopenharmony_ci        return JSTaggedValue(base::NAN_VALUE);
7304514f5e3Sopenharmony_ci    }
7314514f5e3Sopenharmony_ci    CString year = ToCString(fields[YEAR]);
7324514f5e3Sopenharmony_ci    if (year[0] == NEG) {
7334514f5e3Sopenharmony_ci        year = StrToTargetLength(year, STR_LENGTH_YEAR + STR_LENGTH_OTHERS);
7344514f5e3Sopenharmony_ci    } else if (year.length() > STR_LENGTH_YEAR) {
7354514f5e3Sopenharmony_ci        year = PLUS + StrToTargetLength(year, STR_LENGTH_YEAR + STR_LENGTH_OTHERS);
7364514f5e3Sopenharmony_ci    } else {
7374514f5e3Sopenharmony_ci        year = StrToTargetLength(year, STR_LENGTH_YEAR);
7384514f5e3Sopenharmony_ci    }
7394514f5e3Sopenharmony_ci    CString str;
7404514f5e3Sopenharmony_ci    str.reserve(ISO_STRING_LENGTH);
7414514f5e3Sopenharmony_ci    str.append(year) // Append year
7424514f5e3Sopenharmony_ci        .append(NEG_STR); // Append NEG
7434514f5e3Sopenharmony_ci    ConvertAndAppend(fields[MONTH] + 1, STR_LENGTH_OTHERS, str);
7444514f5e3Sopenharmony_ci    str += NEG;
7454514f5e3Sopenharmony_ci    ConvertAndAppend(fields[DAYS], STR_LENGTH_OTHERS, str);
7464514f5e3Sopenharmony_ci    str += FLAG_TIME;
7474514f5e3Sopenharmony_ci    ConvertAndAppend(fields[HOUR], STR_LENGTH_OTHERS, str);
7484514f5e3Sopenharmony_ci    str += COLON;
7494514f5e3Sopenharmony_ci    ConvertAndAppend(fields[MIN], STR_LENGTH_OTHERS, str);
7504514f5e3Sopenharmony_ci    str += COLON;
7514514f5e3Sopenharmony_ci    ConvertAndAppend(fields[SEC], STR_LENGTH_OTHERS, str);
7524514f5e3Sopenharmony_ci    str += POINT;
7534514f5e3Sopenharmony_ci    ConvertAndAppend(fields[MS], STR_LENGTH_OTHERS + 1, str);
7544514f5e3Sopenharmony_ci    str += FLAG_UTC;
7554514f5e3Sopenharmony_ci    return thread->GetEcmaVM()->GetFactory()->NewFromASCII(str).GetTaggedValue();
7564514f5e3Sopenharmony_ci}
7574514f5e3Sopenharmony_ci
7584514f5e3Sopenharmony_ci// 20.4.4.41
7594514f5e3Sopenharmony_ciJSTaggedValue JSDate::ToString(JSThread *thread) const
7604514f5e3Sopenharmony_ci{
7614514f5e3Sopenharmony_ci    int localMin = 0;
7624514f5e3Sopenharmony_ci    std::array<int64_t, DATE_LENGTH> fields = {0};
7634514f5e3Sopenharmony_ci    if (!GetThisDateValues(&fields, true)) {
7644514f5e3Sopenharmony_ci        return JSTaggedValue(base::NAN_VALUE);
7654514f5e3Sopenharmony_ci    }
7664514f5e3Sopenharmony_ci    CString localTime;
7674514f5e3Sopenharmony_ci    localMin = GetLocalOffsetFromOS(static_cast<int64_t>(this->GetTimeValue().GetDouble()), true);
7684514f5e3Sopenharmony_ci    if (localMin >= 0) {
7694514f5e3Sopenharmony_ci        localTime += PLUS;
7704514f5e3Sopenharmony_ci    } else {
7714514f5e3Sopenharmony_ci        localTime += NEG;
7724514f5e3Sopenharmony_ci        localMin = -localMin;
7734514f5e3Sopenharmony_ci    }
7744514f5e3Sopenharmony_ci    localTime = localTime + StrToTargetLength(ToCString(localMin / MINUTE_PER_HOUR), STR_LENGTH_OTHERS);
7754514f5e3Sopenharmony_ci    localTime = localTime + StrToTargetLength(ToCString(localMin % MINUTE_PER_HOUR), STR_LENGTH_OTHERS);
7764514f5e3Sopenharmony_ci    CString str;
7774514f5e3Sopenharmony_ci    str.reserve(TO_STRING_LENGTH);
7784514f5e3Sopenharmony_ci    str.append(WEEK_DAY_NAME[fields[WEEKDAY]]) // Append weekday name
7794514f5e3Sopenharmony_ci        .append(SPACE_STR) // Append SPACE
7804514f5e3Sopenharmony_ci        .append(MONTH_NAME[fields[MONTH]]) // Append mouth name
7814514f5e3Sopenharmony_ci        .append(SPACE_STR); // Append SPACE
7824514f5e3Sopenharmony_ci    ConvertAndAppend(fields[DAYS], STR_LENGTH_OTHERS, str);
7834514f5e3Sopenharmony_ci    str += SPACE;
7844514f5e3Sopenharmony_ci    ConvertAndAppend(fields[YEAR], STR_LENGTH_YEAR, str);
7854514f5e3Sopenharmony_ci    str += SPACE;
7864514f5e3Sopenharmony_ci    ConvertAndAppend(fields[HOUR], STR_LENGTH_OTHERS, str);
7874514f5e3Sopenharmony_ci    str += COLON;
7884514f5e3Sopenharmony_ci    ConvertAndAppend(fields[MIN], STR_LENGTH_OTHERS, str);
7894514f5e3Sopenharmony_ci    str += COLON;
7904514f5e3Sopenharmony_ci    ConvertAndAppend(fields[SEC], STR_LENGTH_OTHERS, str);
7914514f5e3Sopenharmony_ci    str.append(SPACE_STR) // Append SPACE
7924514f5e3Sopenharmony_ci        .append("GMT") // Append GMT
7934514f5e3Sopenharmony_ci        .append(localTime); // Append localTime
7944514f5e3Sopenharmony_ci    return thread->GetEcmaVM()->GetFactory()->NewFromASCII(str).GetTaggedValue();
7954514f5e3Sopenharmony_ci}
7964514f5e3Sopenharmony_ci
7974514f5e3Sopenharmony_ci// 20.4.4.42
7984514f5e3Sopenharmony_ciJSTaggedValue JSDate::ToTimeString(JSThread *thread) const
7994514f5e3Sopenharmony_ci{
8004514f5e3Sopenharmony_ci    int localMin = 0;
8014514f5e3Sopenharmony_ci    std::array<int64_t, DATE_LENGTH> fields = {0};
8024514f5e3Sopenharmony_ci    if (!GetThisDateValues(&fields, true)) {
8034514f5e3Sopenharmony_ci        return JSTaggedValue(base::NAN_VALUE);
8044514f5e3Sopenharmony_ci    }
8054514f5e3Sopenharmony_ci    CString localTime;
8064514f5e3Sopenharmony_ci    localMin = GetLocalOffsetFromOS(static_cast<int64_t>(this->GetTimeValue().GetDouble()), true);
8074514f5e3Sopenharmony_ci    if (localMin >= 0) {
8084514f5e3Sopenharmony_ci        localTime += PLUS;
8094514f5e3Sopenharmony_ci    } else {
8104514f5e3Sopenharmony_ci        localTime += NEG;
8114514f5e3Sopenharmony_ci        localMin = -localMin;
8124514f5e3Sopenharmony_ci    }
8134514f5e3Sopenharmony_ci    localTime = localTime + StrToTargetLength(ToCString(localMin / MINUTE_PER_HOUR), STR_LENGTH_OTHERS);
8144514f5e3Sopenharmony_ci    localTime = localTime + StrToTargetLength(ToCString(localMin % MINUTE_PER_HOUR), STR_LENGTH_OTHERS);
8154514f5e3Sopenharmony_ci    CString str;
8164514f5e3Sopenharmony_ci    str.reserve(TIME_STRING_LENGTH);
8174514f5e3Sopenharmony_ci    ConvertAndAppend(fields[HOUR], STR_LENGTH_OTHERS, str);
8184514f5e3Sopenharmony_ci    str += COLON;
8194514f5e3Sopenharmony_ci    ConvertAndAppend(fields[MIN], STR_LENGTH_OTHERS, str);
8204514f5e3Sopenharmony_ci    str += COLON;
8214514f5e3Sopenharmony_ci    ConvertAndAppend(fields[SEC], STR_LENGTH_OTHERS, str);
8224514f5e3Sopenharmony_ci    str.append(SPACE_STR) // Append SPACE
8234514f5e3Sopenharmony_ci        .append("GMT") // Append GMT
8244514f5e3Sopenharmony_ci        .append(localTime); // Append localTime
8254514f5e3Sopenharmony_ci    return thread->GetEcmaVM()->GetFactory()->NewFromASCII(str).GetTaggedValue();
8264514f5e3Sopenharmony_ci}
8274514f5e3Sopenharmony_ci
8284514f5e3Sopenharmony_ci// 20.4.4.43
8294514f5e3Sopenharmony_ciJSTaggedValue JSDate::ToUTCString(JSThread *thread) const
8304514f5e3Sopenharmony_ci{
8314514f5e3Sopenharmony_ci    std::array<int64_t, DATE_LENGTH> fields = {0};
8324514f5e3Sopenharmony_ci    if (!GetThisDateValues(&fields, false)) {
8334514f5e3Sopenharmony_ci        return JSTaggedValue(base::NAN_VALUE);
8344514f5e3Sopenharmony_ci    }
8354514f5e3Sopenharmony_ci    CString str;
8364514f5e3Sopenharmony_ci    str.reserve(UTC_STRING_LENGTH);
8374514f5e3Sopenharmony_ci    str.append(WEEK_DAY_NAME[fields[WEEKDAY]]) // Append weekday name
8384514f5e3Sopenharmony_ci        .append(COMMA_STR) // Append COMMA
8394514f5e3Sopenharmony_ci        .append(SPACE_STR); // Append SPACE
8404514f5e3Sopenharmony_ci    ConvertAndAppend(fields[DAYS], STR_LENGTH_OTHERS, str);
8414514f5e3Sopenharmony_ci    str.append(SPACE_STR) // Append SPACE
8424514f5e3Sopenharmony_ci        .append(MONTH_NAME[fields[MONTH]]) // Append mouth name
8434514f5e3Sopenharmony_ci        .append(SPACE_STR); // Append SPACE
8444514f5e3Sopenharmony_ci    ConvertAndAppend(fields[YEAR], STR_LENGTH_YEAR, str);
8454514f5e3Sopenharmony_ci    str += SPACE;
8464514f5e3Sopenharmony_ci    ConvertAndAppend(fields[HOUR], STR_LENGTH_OTHERS, str);
8474514f5e3Sopenharmony_ci    str += COLON;
8484514f5e3Sopenharmony_ci    ConvertAndAppend(fields[MIN], STR_LENGTH_OTHERS, str);
8494514f5e3Sopenharmony_ci    str += COLON;
8504514f5e3Sopenharmony_ci    ConvertAndAppend(fields[SEC], STR_LENGTH_OTHERS, str);
8514514f5e3Sopenharmony_ci    str.append(SPACE_STR) // Append SPACE
8524514f5e3Sopenharmony_ci        .append("GMT"); // Append GMT
8534514f5e3Sopenharmony_ci    return thread->GetEcmaVM()->GetFactory()->NewFromASCII(str).GetTaggedValue();
8544514f5e3Sopenharmony_ci}
8554514f5e3Sopenharmony_ci
8564514f5e3Sopenharmony_ci// 20.4.4.44
8574514f5e3Sopenharmony_ciJSTaggedValue JSDate::ValueOf() const
8584514f5e3Sopenharmony_ci{
8594514f5e3Sopenharmony_ci    return this->GetTimeValue();
8604514f5e3Sopenharmony_ci}
8614514f5e3Sopenharmony_ci
8624514f5e3Sopenharmony_ci// static
8634514f5e3Sopenharmony_civoid JSDate::GetDateValues(double timeMs, std::array<int64_t, DATE_LENGTH> *date, bool isLocal)
8644514f5e3Sopenharmony_ci{
8654514f5e3Sopenharmony_ci    int64_t tz = 0;
8664514f5e3Sopenharmony_ci    int64_t timeMsInt = static_cast<int64_t>(timeMs);
8674514f5e3Sopenharmony_ci    if (isLocal) {  // timezone offset
8684514f5e3Sopenharmony_ci        tz = GetLocalOffsetFromOS(timeMsInt, isLocal);
8694514f5e3Sopenharmony_ci        timeMsInt += tz * MS_PER_SECOND * SEC_PER_MINUTE;
8704514f5e3Sopenharmony_ci    }
8714514f5e3Sopenharmony_ci
8724514f5e3Sopenharmony_ci    DateUtils::TransferTimeToDate(timeMsInt, date);
8734514f5e3Sopenharmony_ci    (*date)[TIMEZONE] = -tz;
8744514f5e3Sopenharmony_ci}
8754514f5e3Sopenharmony_ci
8764514f5e3Sopenharmony_cidouble JSDate::GetDateValue(double timeMs, uint8_t code, bool isLocal) const
8774514f5e3Sopenharmony_ci{
8784514f5e3Sopenharmony_ci    if (std::isnan(timeMs)) {
8794514f5e3Sopenharmony_ci        return base::NAN_VALUE;
8804514f5e3Sopenharmony_ci    }
8814514f5e3Sopenharmony_ci    std::array<int64_t, DATE_LENGTH> date = {0};
8824514f5e3Sopenharmony_ci    GetDateValues(timeMs, &date, isLocal);
8834514f5e3Sopenharmony_ci    return static_cast<double>(date[code]);
8844514f5e3Sopenharmony_ci}
8854514f5e3Sopenharmony_ci
8864514f5e3Sopenharmony_ciJSTaggedValue JSDate::SetDateValue(EcmaRuntimeCallInfo *argv, uint32_t code, bool isLocal) const
8874514f5e3Sopenharmony_ci{
8884514f5e3Sopenharmony_ci    // get date values.
8894514f5e3Sopenharmony_ci    std::array<int64_t, DATE_LENGTH> date = {0};
8904514f5e3Sopenharmony_ci    double timeMs = this->GetTimeValue().GetDouble();
8914514f5e3Sopenharmony_ci
8924514f5e3Sopenharmony_ci    // get values from argv.
8934514f5e3Sopenharmony_ci    uint32_t argc = argv->GetArgsNumber();
8944514f5e3Sopenharmony_ci    if (argc == 0) {
8954514f5e3Sopenharmony_ci        return JSTaggedValue(base::NAN_VALUE);
8964514f5e3Sopenharmony_ci    }
8974514f5e3Sopenharmony_ci
8984514f5e3Sopenharmony_ci    uint32_t firstValue = code & CODE_FLAG;
8994514f5e3Sopenharmony_ci    uint32_t endValue = (code >> CODE_4_BIT) & CODE_FLAG;
9004514f5e3Sopenharmony_ci    uint32_t count = endValue - firstValue;
9014514f5e3Sopenharmony_ci
9024514f5e3Sopenharmony_ci    if (argc < count) {
9034514f5e3Sopenharmony_ci        count = argc;
9044514f5e3Sopenharmony_ci    }
9054514f5e3Sopenharmony_ci    if (std::isnan(timeMs) && firstValue == 0) {
9064514f5e3Sopenharmony_ci        timeMs = 0.0;
9074514f5e3Sopenharmony_ci        GetDateValues(timeMs, &date, false);
9084514f5e3Sopenharmony_ci    } else {
9094514f5e3Sopenharmony_ci        GetDateValues(timeMs, &date, isLocal);
9104514f5e3Sopenharmony_ci    }
9114514f5e3Sopenharmony_ci
9124514f5e3Sopenharmony_ci    for (uint32_t i = 0; i < count; i++) {
9134514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> value = base::BuiltinsBase::GetCallArg(argv, i);
9144514f5e3Sopenharmony_ci        JSThread *thread = argv->GetThread();
9154514f5e3Sopenharmony_ci        JSTaggedNumber res = JSTaggedValue::ToNumber(thread, value);
9164514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
9174514f5e3Sopenharmony_ci        double temp = res.GetNumber();
9184514f5e3Sopenharmony_ci        if (std::isnan(temp)) {
9194514f5e3Sopenharmony_ci            return JSTaggedValue(base::NAN_VALUE);
9204514f5e3Sopenharmony_ci        }
9214514f5e3Sopenharmony_ci        date[firstValue + i] = NumberHelper::TruncateDouble(temp);
9224514f5e3Sopenharmony_ci    }
9234514f5e3Sopenharmony_ci    // set date values.
9244514f5e3Sopenharmony_ci    return JSTaggedValue(SetDateValues(&date, isLocal));
9254514f5e3Sopenharmony_ci}
9264514f5e3Sopenharmony_ci
9274514f5e3Sopenharmony_ci// static
9284514f5e3Sopenharmony_cidouble JSDate::SetDateValues(const std::array<int64_t, DATE_LENGTH> *date, bool isLocal)
9294514f5e3Sopenharmony_ci{
9304514f5e3Sopenharmony_ci    int64_t month = DateUtils::Mod((*date)[MONTH], MONTH_PER_YEAR);
9314514f5e3Sopenharmony_ci    int64_t year = (*date)[YEAR] + ((*date)[MONTH] - month) / MONTH_PER_YEAR;
9324514f5e3Sopenharmony_ci    int64_t days = DateUtils::GetDaysFromYear(year);
9334514f5e3Sopenharmony_ci    int index = DateUtils::IsLeap(year) ? 1 : 0;
9344514f5e3Sopenharmony_ci    days += DAYS_FROM_MONTH[index][month];
9354514f5e3Sopenharmony_ci
9364514f5e3Sopenharmony_ci    days += (*date)[DAYS] - 1;
9374514f5e3Sopenharmony_ci    int64_t millisecond =
9384514f5e3Sopenharmony_ci        (((*date)[HOUR] * MIN_PER_HOUR + (*date)[MIN]) * SEC_PER_MINUTE + (*date)[SEC]) * MS_PER_SECOND + (*date)[MS];
9394514f5e3Sopenharmony_ci    int64_t result = days * MS_PER_DAY + millisecond;
9404514f5e3Sopenharmony_ci    if (isLocal) {
9414514f5e3Sopenharmony_ci        int64_t offset = GetLocalOffsetFromOS(result, isLocal) * SEC_PER_MINUTE * MS_PER_SECOND;
9424514f5e3Sopenharmony_ci        result -= offset;
9434514f5e3Sopenharmony_ci    }
9444514f5e3Sopenharmony_ci    return TimeClip(result);
9454514f5e3Sopenharmony_ci}
9464514f5e3Sopenharmony_ci
9474514f5e3Sopenharmony_cidouble JSDate::SetDateValues(int64_t year, int64_t month, int64_t day)
9484514f5e3Sopenharmony_ci{
9494514f5e3Sopenharmony_ci    if (year >= 0 && year < HUNDRED) {
9504514f5e3Sopenharmony_ci        year += NINETEEN_HUNDRED_YEAR;
9514514f5e3Sopenharmony_ci    }
9524514f5e3Sopenharmony_ci    int64_t m = DateUtils::Mod(month, MONTH_PER_YEAR);
9534514f5e3Sopenharmony_ci    int64_t y = year + (month - m) / MONTH_PER_YEAR;
9544514f5e3Sopenharmony_ci    int64_t d = DateUtils::GetDaysFromYear(y);
9554514f5e3Sopenharmony_ci    int index = DateUtils::IsLeap(y) ? 1 : 0;
9564514f5e3Sopenharmony_ci    d += DAYS_FROM_MONTH[index][m] + day - 1;
9574514f5e3Sopenharmony_ci    int64_t result = d * MS_PER_DAY;
9584514f5e3Sopenharmony_ci
9594514f5e3Sopenharmony_ci    int64_t offset = GetLocalOffsetFromOS(result, true) * SEC_PER_MINUTE * MS_PER_SECOND;
9604514f5e3Sopenharmony_ci    result -= offset;
9614514f5e3Sopenharmony_ci    return TimeClip(result);
9624514f5e3Sopenharmony_ci}
9634514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
964