14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 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 "builtins_date_time_format.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/intl/locale_helper.h"
194514f5e3Sopenharmony_ci#include "ecmascript/global_env.h"
204514f5e3Sopenharmony_ci#include "ecmascript/js_date.h"
214514f5e3Sopenharmony_ci#include "ecmascript/js_date_time_format.h"
224514f5e3Sopenharmony_ci#include "ecmascript/js_function.h"
234514f5e3Sopenharmony_ci#include "ecmascript/js_intl.h"
244514f5e3Sopenharmony_ci
254514f5e3Sopenharmony_cinamespace panda::ecmascript::builtins {
264514f5e3Sopenharmony_ci// 13.2.1 Intl.DateTimeFormat ( [ locales [ , options ] ] )
274514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDateTimeFormat::DateTimeFormatConstructor(EcmaRuntimeCallInfo *argv)
284514f5e3Sopenharmony_ci{
294514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
304514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DateTimeFormat, Constructor);
314514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope scope(thread);
324514f5e3Sopenharmony_ci    EcmaVM *ecmaVm = thread->GetEcmaVM();
334514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
344514f5e3Sopenharmony_ci    ObjectFactory *factory = ecmaVm->GetFactory();
354514f5e3Sopenharmony_ci
364514f5e3Sopenharmony_ci    // 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
374514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
384514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
394514f5e3Sopenharmony_ci    if (newTarget->IsUndefined()) {
404514f5e3Sopenharmony_ci        newTarget = constructor;
414514f5e3Sopenharmony_ci    }
424514f5e3Sopenharmony_ci
434514f5e3Sopenharmony_ci    // 2. Let dateTimeFormat be ? OrdinaryCreateFromConstructor(newTarget, "%DateTimeFormatPrototype%", «
444514f5e3Sopenharmony_ci    //    [[InitializedDateTimeFormat]], [[Locale]], [[Calendar]], [[NumberingSystem]], [[TimeZone]], [[Weekday]],
454514f5e3Sopenharmony_ci    //    [[Era]], [[Year]], [[Month]], [[Day]], [[Hour]], [[Minute]], [[Second]], [[TimeZoneName]], [[HourCycle]],
464514f5e3Sopenharmony_ci    //    [[Pattern]], [[BoundFormat]] »).
474514f5e3Sopenharmony_ci    JSHandle<JSObject> newObject = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
484514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
494514f5e3Sopenharmony_ci    JSHandle<JSDateTimeFormat> dateTimeFormat = JSHandle<JSDateTimeFormat>::Cast(newObject);
504514f5e3Sopenharmony_ci
514514f5e3Sopenharmony_ci    // 3. Perform ? InitializeDateTimeFormat(dateTimeFormat, locales, options).
524514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
534514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
544514f5e3Sopenharmony_ci    JSHandle<JSDateTimeFormat> dtf =
554514f5e3Sopenharmony_ci        JSDateTimeFormat::InitializeDateTimeFormat(thread, dateTimeFormat, locales, options);
564514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
574514f5e3Sopenharmony_ci
584514f5e3Sopenharmony_ci    // 4. Let this be the this value.
594514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisValue = GetThis(argv);
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_ci    // 5. If NewTarget is undefined and Type(this) is Object and ? InstanceofOperator(this, %DateTimeFormat%) is true,
624514f5e3Sopenharmony_ci    //    then
634514f5e3Sopenharmony_ci    //    a. Perform ? DefinePropertyOrThrow(this, %Intl%.[[FallbackSymbol]], PropertyDescriptor{ [[Value]]:
644514f5e3Sopenharmony_ci    //       dateTimeFormat, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }).
654514f5e3Sopenharmony_ci    //    b. Return this.
664514f5e3Sopenharmony_ci    if (GetNewTarget(argv)->IsUndefined() && thisValue->IsJSObject()) {
674514f5e3Sopenharmony_ci        bool isInstanceOf = JSFunction::OrdinaryHasInstance(thread, env->GetDateTimeFormatFunction(), thisValue);
684514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
694514f5e3Sopenharmony_ci        if (isInstanceOf) {
704514f5e3Sopenharmony_ci            PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>::Cast(dtf), false, false, false);
714514f5e3Sopenharmony_ci            JSHandle<JSTaggedValue> key(thread, JSHandle<JSIntl>::Cast(env->GetIntlFunction())->GetFallbackSymbol());
724514f5e3Sopenharmony_ci            JSTaggedValue::DefinePropertyOrThrow(thread, thisValue, key, descriptor);
734514f5e3Sopenharmony_ci            RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
744514f5e3Sopenharmony_ci            return thisValue.GetTaggedValue();
754514f5e3Sopenharmony_ci        }
764514f5e3Sopenharmony_ci    }
774514f5e3Sopenharmony_ci
784514f5e3Sopenharmony_ci    // 6. Return dateTimeFormat.
794514f5e3Sopenharmony_ci    return dtf.GetTaggedValue();
804514f5e3Sopenharmony_ci}
814514f5e3Sopenharmony_ci
824514f5e3Sopenharmony_ci// 13.3.2 Intl.DateTimeFormat.supportedLocalesOf ( locales [ , options ] )
834514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDateTimeFormat::SupportedLocalesOf(EcmaRuntimeCallInfo *argv)
844514f5e3Sopenharmony_ci{
854514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
864514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DateTimeFormat, SupportedLocalesOf);
874514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope scope(thread);
884514f5e3Sopenharmony_ci    // 1. Let availableLocales be %DateTimeFormat%.[[AvailableLocales]].
894514f5e3Sopenharmony_ci    JSHandle<TaggedArray> availableLocales = JSDateTimeFormat::GainAvailableLocales(thread);
904514f5e3Sopenharmony_ci
914514f5e3Sopenharmony_ci    // 2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
924514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
934514f5e3Sopenharmony_ci    JSHandle<TaggedArray> requestedLocales = intl::LocaleHelper::CanonicalizeLocaleList(thread, locales);
944514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
954514f5e3Sopenharmony_ci
964514f5e3Sopenharmony_ci    // 3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
974514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
984514f5e3Sopenharmony_ci    JSHandle<JSArray> result = JSLocale::SupportedLocales(thread, availableLocales, requestedLocales, options);
994514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1004514f5e3Sopenharmony_ci    return result.GetTaggedValue();
1014514f5e3Sopenharmony_ci}
1024514f5e3Sopenharmony_ci
1034514f5e3Sopenharmony_ci// 13.4.3 get Intl.DateTimeFormat.prototype.format
1044514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDateTimeFormat::Format(EcmaRuntimeCallInfo *argv)
1054514f5e3Sopenharmony_ci{
1064514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
1074514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DateTimeFormat, Format);
1084514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope scope(thread);
1094514f5e3Sopenharmony_ci
1104514f5e3Sopenharmony_ci    // 1. Let dtf be this value.
1114514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisValue = GetThis(argv);
1124514f5e3Sopenharmony_ci
1134514f5e3Sopenharmony_ci    // 2. If Type(dtf) is not Object, throw a TypeError exception.
1144514f5e3Sopenharmony_ci    if (!thisValue->IsJSObject()) {
1154514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "dtf is not object", JSTaggedValue::Exception());
1164514f5e3Sopenharmony_ci    }
1174514f5e3Sopenharmony_ci
1184514f5e3Sopenharmony_ci    // 3. Let dtf be ? UnwrapDateTimeFormat(dtf).
1194514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> dtfValue = JSDateTimeFormat::UnwrapDateTimeFormat(thread, thisValue);
1204514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1214514f5e3Sopenharmony_ci    if (dtfValue->IsUndefined()) {
1224514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "dtfValue is not object", JSTaggedValue::Exception());
1234514f5e3Sopenharmony_ci    }
1244514f5e3Sopenharmony_ci
1254514f5e3Sopenharmony_ci    // 4. If dtf.[[BoundFormat]] is undefined, then
1264514f5e3Sopenharmony_ci    //    a. Let F be a new built-in function object as defined in DateTime Format Functions (13.1.5).
1274514f5e3Sopenharmony_ci    //    b. Set F.[[DateTimeFormat]] to dtf.
1284514f5e3Sopenharmony_ci    //    c. Set dtf.[[BoundFormat]] to F.
1294514f5e3Sopenharmony_ci    // 5. Return dtf.[[BoundFormat]].
1304514f5e3Sopenharmony_ci    JSHandle<JSDateTimeFormat> dtf = JSHandle<JSDateTimeFormat>::Cast(dtfValue);
1314514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> boundFormat(thread, dtf->GetBoundFormat());
1324514f5e3Sopenharmony_ci    if (boundFormat->IsUndefined()) {
1334514f5e3Sopenharmony_ci        ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1344514f5e3Sopenharmony_ci        JSHandle<JSIntlBoundFunction> intlBoundFunc = factory->NewJSIntlBoundFunction(
1354514f5e3Sopenharmony_ci            MethodIndex::BUILTINS_DATE_TIME_FORMAT_ANONYMOUS_DATE_TIME_FORMAT);
1364514f5e3Sopenharmony_ci        intlBoundFunc->SetDateTimeFormat(thread, dtf);
1374514f5e3Sopenharmony_ci        dtf->SetBoundFormat(thread, intlBoundFunc);
1384514f5e3Sopenharmony_ci    }
1394514f5e3Sopenharmony_ci    return dtf->GetBoundFormat();
1404514f5e3Sopenharmony_ci}
1414514f5e3Sopenharmony_ci
1424514f5e3Sopenharmony_ci// 13.1.5 DateTime Format Functions
1434514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDateTimeFormat::AnonymousDateTimeFormat(EcmaRuntimeCallInfo *argv)
1444514f5e3Sopenharmony_ci{
1454514f5e3Sopenharmony_ci    // A DateTime format function is an anonymous built-in function that has a [[DateTimeFormat]] internal slot.
1464514f5e3Sopenharmony_ci    // When a DateTime format function F is called with optional argument date, the following steps are taken:
1474514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
1484514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DateTimeFormat, AnonymousDateTimeFormat);
1494514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope scope(thread);
1504514f5e3Sopenharmony_ci    JSHandle<JSIntlBoundFunction> intlBoundFunc = JSHandle<JSIntlBoundFunction>::Cast(GetConstructor(argv));
1514514f5e3Sopenharmony_ci
1524514f5e3Sopenharmony_ci    // 1. Let dtf be F.[[DateTimeFormat]].
1534514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> dtf(thread, intlBoundFunc->GetDateTimeFormat());
1544514f5e3Sopenharmony_ci
1554514f5e3Sopenharmony_ci    // 2. Assert: Type(dtf) is Object and dtf has an [[InitializedDateTimeFormat]] internal slot.
1564514f5e3Sopenharmony_ci    ASSERT_PRINT(dtf->IsJSObject() && dtf->IsJSDateTimeFormat(), "dtf is not object or JSDateTimeFormat");
1574514f5e3Sopenharmony_ci
1584514f5e3Sopenharmony_ci    // 3. If date is not provided or is undefined, then
1594514f5e3Sopenharmony_ci    //    a. Let x be Call(%Date_now%, undefined).
1604514f5e3Sopenharmony_ci    // 4. Else,
1614514f5e3Sopenharmony_ci    //    a. Let x be ? ToNumber(date).
1624514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> date = GetCallArg(argv, 0);
1634514f5e3Sopenharmony_ci    double x = 0.0;
1644514f5e3Sopenharmony_ci    if (date->IsUndefined()) {
1654514f5e3Sopenharmony_ci        x = JSDate::Now().GetNumber();
1664514f5e3Sopenharmony_ci    } else {
1674514f5e3Sopenharmony_ci        JSTaggedNumber xNumber = JSTaggedValue::ToNumber(thread, date);
1684514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1694514f5e3Sopenharmony_ci        x = xNumber.GetNumber();
1704514f5e3Sopenharmony_ci    }
1714514f5e3Sopenharmony_ci
1724514f5e3Sopenharmony_ci    // 5. Return ? FormatDateTime(dtf, x).
1734514f5e3Sopenharmony_ci    JSHandle<EcmaString> result = JSDateTimeFormat::FormatDateTime(thread, JSHandle<JSDateTimeFormat>::Cast(dtf), x);
1744514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1754514f5e3Sopenharmony_ci    return result.GetTaggedValue();
1764514f5e3Sopenharmony_ci}
1774514f5e3Sopenharmony_ci
1784514f5e3Sopenharmony_ci// 13.4.4 Intl.DateTimeFormat.prototype.formatToParts ( date )
1794514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDateTimeFormat::FormatToParts(EcmaRuntimeCallInfo *argv)
1804514f5e3Sopenharmony_ci{
1814514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
1824514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DateTimeFormat, FormatToParts);
1834514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope scope(thread);
1844514f5e3Sopenharmony_ci    // 1. Let dtf be this value.
1854514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> dtf = GetThis(argv);
1864514f5e3Sopenharmony_ci    // 2. Perform ? RequireInternalSlot(dtf, [[InitializedDateTimeFormat]]).
1874514f5e3Sopenharmony_ci    if (!dtf->IsJSDateTimeFormat()) {
1884514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "is not JSDateTimeFormat", JSTaggedValue::Exception());
1894514f5e3Sopenharmony_ci    }
1904514f5e3Sopenharmony_ci
1914514f5e3Sopenharmony_ci    // 3. If date is undefined, then
1924514f5e3Sopenharmony_ci    //    a. Let x be Call(%Date_now%, undefined).
1934514f5e3Sopenharmony_ci    // 4. Else,
1944514f5e3Sopenharmony_ci    //    a. Let x be ? ToNumber(date).
1954514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> date = GetCallArg(argv, 0);
1964514f5e3Sopenharmony_ci    double x = 0.0;
1974514f5e3Sopenharmony_ci    if (date->IsUndefined()) {
1984514f5e3Sopenharmony_ci        x = JSDate::Now().GetNumber();
1994514f5e3Sopenharmony_ci    } else {
2004514f5e3Sopenharmony_ci        JSTaggedNumber xNumber = JSTaggedValue::ToNumber(thread, date);
2014514f5e3Sopenharmony_ci        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2024514f5e3Sopenharmony_ci        x = xNumber.GetNumber();
2034514f5e3Sopenharmony_ci    }
2044514f5e3Sopenharmony_ci
2054514f5e3Sopenharmony_ci    double xValue = JSDate::TimeClip(x);
2064514f5e3Sopenharmony_ci    if (std::isnan(xValue)) {
2074514f5e3Sopenharmony_ci        THROW_RANGE_ERROR_AND_RETURN(thread, "Invalid time value", JSTaggedValue::Exception());
2084514f5e3Sopenharmony_ci    }
2094514f5e3Sopenharmony_ci
2104514f5e3Sopenharmony_ci    // 5. Return ? FormatDateTimeToParts(dtf, x).
2114514f5e3Sopenharmony_ci    JSHandle<JSArray> result =
2124514f5e3Sopenharmony_ci        JSDateTimeFormat::FormatDateTimeToParts(thread, JSHandle<JSDateTimeFormat>::Cast(dtf), xValue);
2134514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2144514f5e3Sopenharmony_ci    return result.GetTaggedValue();
2154514f5e3Sopenharmony_ci}
2164514f5e3Sopenharmony_ci
2174514f5e3Sopenharmony_ci// 13.4.5 Intl.DateTimeFormat.prototype.resolvedOptions ()
2184514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDateTimeFormat::ResolvedOptions(EcmaRuntimeCallInfo *argv)
2194514f5e3Sopenharmony_ci{
2204514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
2214514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DateTimeFormat, ResolvedOptions);
2224514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope scope(thread);
2234514f5e3Sopenharmony_ci    // 1. Let dtf be this value.
2244514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisValue = GetThis(argv);
2254514f5e3Sopenharmony_ci    // 2. If Type(dtf) is not Object, throw a TypeError exception.
2264514f5e3Sopenharmony_ci    if (!thisValue->IsJSObject()) {
2274514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "this is not object", JSTaggedValue::Exception());
2284514f5e3Sopenharmony_ci    }
2294514f5e3Sopenharmony_ci    // 3. Let dtf be ? UnwrapDateTimeFormat(dtf).
2304514f5e3Sopenharmony_ci    thisValue = JSDateTimeFormat::UnwrapDateTimeFormat(thread, thisValue);
2314514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2324514f5e3Sopenharmony_ci
2334514f5e3Sopenharmony_ci    // Perform ? RequireInternalSlot(dtf, [[InitializedDateTimeFormat]]).
2344514f5e3Sopenharmony_ci    if (!thisValue->IsJSDateTimeFormat()) {
2354514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "dtf is not JSDateTimeFormat", JSTaggedValue::Exception());
2364514f5e3Sopenharmony_ci    }
2374514f5e3Sopenharmony_ci
2384514f5e3Sopenharmony_ci    auto ecmaVm = thread->GetEcmaVM();
2394514f5e3Sopenharmony_ci    JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
2404514f5e3Sopenharmony_ci    ObjectFactory *factory = ecmaVm->GetFactory();
2414514f5e3Sopenharmony_ci    JSHandle<JSFunction> ctor(env->GetObjectFunction());
2424514f5e3Sopenharmony_ci    JSHandle<JSObject> options(factory->NewJSObjectByConstructor(ctor));
2434514f5e3Sopenharmony_ci    JSDateTimeFormat::ResolvedOptions(thread, JSHandle<JSDateTimeFormat>::Cast(thisValue), options);
2444514f5e3Sopenharmony_ci    // 6. Return options.
2454514f5e3Sopenharmony_ci    return options.GetTaggedValue();
2464514f5e3Sopenharmony_ci}
2474514f5e3Sopenharmony_ci
2484514f5e3Sopenharmony_ci// Intl.DateTimeFormat.prototype.formatRange
2494514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDateTimeFormat::FormatRange(EcmaRuntimeCallInfo *argv)
2504514f5e3Sopenharmony_ci{
2514514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
2524514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DateTimeFormat, FormatRange);
2534514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope scope(thread);
2544514f5e3Sopenharmony_ci
2554514f5e3Sopenharmony_ci    // 1. Let dtf be this value.
2564514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisValue = GetThis(argv);
2574514f5e3Sopenharmony_ci    // 2. If Type(dtf) is not Object, throw a TypeError exception.
2584514f5e3Sopenharmony_ci    if (!thisValue->IsJSObject()) {
2594514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "this is not object", JSTaggedValue::Exception());
2604514f5e3Sopenharmony_ci    }
2614514f5e3Sopenharmony_ci
2624514f5e3Sopenharmony_ci    // 3. If dtf does not have an [[InitializedDateTimeFormat]] internal slot, throw a TypeError exception.
2634514f5e3Sopenharmony_ci    if (!thisValue->IsJSDateTimeFormat()) {
2644514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "this is not JSDateTimeFormat", JSTaggedValue::Exception());
2654514f5e3Sopenharmony_ci    }
2664514f5e3Sopenharmony_ci
2674514f5e3Sopenharmony_ci    // 4. If startDate is undefined or endDate is undefined, throw a TypeError exception.
2684514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> startDate = GetCallArg(argv, 0);
2694514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> endDate = GetCallArg(argv, 1);
2704514f5e3Sopenharmony_ci    if (startDate->IsUndefined() || endDate->IsUndefined()) {
2714514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "startDate or endDate is undefined", JSTaggedValue::Exception());
2724514f5e3Sopenharmony_ci    }
2734514f5e3Sopenharmony_ci
2744514f5e3Sopenharmony_ci    // 5. Let x be ? ToNumber(startDate).
2754514f5e3Sopenharmony_ci    JSTaggedNumber valueX = JSTaggedValue::ToNumber(thread, startDate);
2764514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2774514f5e3Sopenharmony_ci    double x = valueX.GetNumber();
2784514f5e3Sopenharmony_ci
2794514f5e3Sopenharmony_ci    // 6. Let y be ? ToNumber(endDate).
2804514f5e3Sopenharmony_ci    JSTaggedNumber valueY = JSTaggedValue::ToNumber(thread, endDate);
2814514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2824514f5e3Sopenharmony_ci    double y = valueY.GetNumber();
2834514f5e3Sopenharmony_ci
2844514f5e3Sopenharmony_ci    // 8. Return ? FormatDateTimeRange(dtf, x, y)
2854514f5e3Sopenharmony_ci    JSHandle<JSDateTimeFormat> dtf = JSHandle<JSDateTimeFormat>::Cast(thisValue);
2864514f5e3Sopenharmony_ci    JSHandle<EcmaString> result = JSDateTimeFormat::NormDateTimeRange(thread, dtf, x, y);
2874514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2884514f5e3Sopenharmony_ci    return result.GetTaggedValue();
2894514f5e3Sopenharmony_ci}
2904514f5e3Sopenharmony_ci
2914514f5e3Sopenharmony_ci// Intl.DateTimeFormat.prototype.formatRangeToParts
2924514f5e3Sopenharmony_ciJSTaggedValue BuiltinsDateTimeFormat::FormatRangeToParts(EcmaRuntimeCallInfo *argv)
2934514f5e3Sopenharmony_ci{
2944514f5e3Sopenharmony_ci    JSThread *thread = argv->GetThread();
2954514f5e3Sopenharmony_ci    BUILTINS_API_TRACE(thread, DateTimeFormat, FormatRangeToParts);
2964514f5e3Sopenharmony_ci    [[maybe_unused]] EcmaHandleScope scope(thread);
2974514f5e3Sopenharmony_ci    // 1. Let dtf be this value.
2984514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> thisValue = GetThis(argv);
2994514f5e3Sopenharmony_ci    // 2. If Type(dtf) is not Object, throw a TypeError exception.
3004514f5e3Sopenharmony_ci    if (!thisValue->IsJSObject()) {
3014514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "this is not object", JSTaggedValue::Exception());
3024514f5e3Sopenharmony_ci    }
3034514f5e3Sopenharmony_ci
3044514f5e3Sopenharmony_ci    // 3. If dtf does not have an [[InitializedDateTimeFormat]] internal slot,
3054514f5e3Sopenharmony_ci    //    throw a TypeError exception.
3064514f5e3Sopenharmony_ci    if (!thisValue->IsJSDateTimeFormat()) {
3074514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "this is not JSDateTimeFormat", JSTaggedValue::Exception());
3084514f5e3Sopenharmony_ci    }
3094514f5e3Sopenharmony_ci
3104514f5e3Sopenharmony_ci    // 4. If startDate is undefined or endDate is undefined, throw a TypeError exception.
3114514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> startDate = GetCallArg(argv, 0);
3124514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> endDate = GetCallArg(argv, 1);
3134514f5e3Sopenharmony_ci    if (startDate->IsUndefined() || endDate->IsUndefined()) {
3144514f5e3Sopenharmony_ci        THROW_TYPE_ERROR_AND_RETURN(thread, "startDate or endDate is undefined", JSTaggedValue::Exception());
3154514f5e3Sopenharmony_ci    }
3164514f5e3Sopenharmony_ci
3174514f5e3Sopenharmony_ci    // 5. Let x be ? ToNumber(startDate).
3184514f5e3Sopenharmony_ci    JSTaggedNumber valueX = JSTaggedValue::ToNumber(thread, startDate);
3194514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3204514f5e3Sopenharmony_ci    double x = valueX.GetNumber();
3214514f5e3Sopenharmony_ci
3224514f5e3Sopenharmony_ci    // 6. Let y be ? ToNumber(endDate).
3234514f5e3Sopenharmony_ci    JSTaggedNumber valueY = JSTaggedValue::ToNumber(thread, endDate);
3244514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3254514f5e3Sopenharmony_ci    double y = valueY.GetNumber();
3264514f5e3Sopenharmony_ci
3274514f5e3Sopenharmony_ci    // 8. Return ? FormatDateTimeRangeToParts(dtf, x, y)
3284514f5e3Sopenharmony_ci    JSHandle<JSDateTimeFormat> dtf = JSHandle<JSDateTimeFormat>::Cast(thisValue);
3294514f5e3Sopenharmony_ci    JSHandle<JSArray> result = JSDateTimeFormat::NormDateTimeRangeToParts(thread, dtf, x, y);
3304514f5e3Sopenharmony_ci    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3314514f5e3Sopenharmony_ci    return result.GetTaggedValue();
3324514f5e3Sopenharmony_ci}
3334514f5e3Sopenharmony_ci}  // namespace panda::ecmascript::builtins