• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/builtins/builtins_date_time_format.h"
17 
18 #include <ctime>
19 #include <algorithm>
20 #include "ecmascript/builtins/builtins_array.h"
21 #include "ecmascript/global_env.h"
22 #include "ecmascript/js_date.h"
23 #include "ecmascript/js_date_time_format.h"
24 #include "ecmascript/tests/test_helper.h"
25 
26 using namespace panda::ecmascript;
27 using namespace panda::ecmascript::builtins;
28 
29 namespace panda::test {
30 using BuiltinsArray = ecmascript::builtins::BuiltinsArray;
31 class BuiltinsDateTimeFormatTest : public testing::Test {
32 public:
SetUpTestCase()33     static void SetUpTestCase()
34     {
35         GTEST_LOG_(INFO) << "SetUpTestCase";
36     }
37 
TearDownTestCase()38     static void TearDownTestCase()
39     {
40         GTEST_LOG_(INFO) << "TearDownCase";
41     }
42 
SetUp()43     void SetUp() override
44     {
45         JSRuntimeOptions options;
46 #if PANDA_TARGET_LINUX
47         // for consistency requirement, use ohos_icu4j/data as icu-data-path
48         options.SetIcuDataPath(ICU_PATH);
49 #endif
50         options.SetEnableForceGC(true);
51         instance = JSNApi::CreateEcmaVM(options);
52         instance->SetEnableForceGC(true);
53         ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
54         thread = instance->GetJSThread();
55         scope = new EcmaHandleScope(thread);
56     }
57 
TearDown()58     void TearDown() override
59     {
60         TestHelper::DestroyEcmaVMWithScope(instance, scope);
61     }
62 
63     EcmaVM *instance {nullptr};
64     EcmaHandleScope *scope {nullptr};
65     JSThread *thread {nullptr};
66 };
67 
BuiltinsDateTimeOptionsSet(JSThread * thread)68 static JSTaggedValue BuiltinsDateTimeOptionsSet(JSThread *thread)
69 {
70     auto globalConst = thread->GlobalConstants();
71     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
72     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
73 
74     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
75     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
76 
77     JSHandle<JSTaggedValue> weekDay = globalConst->GetHandledWeekdayString();
78     JSHandle<JSTaggedValue> dayPeriod = globalConst->GetHandledDayPeriodString();
79     JSHandle<JSTaggedValue> hourCycle = globalConst->GetHandledHourCycleString();
80     JSHandle<JSTaggedValue> timeZone = globalConst->GetHandledTimeZoneString();
81     JSHandle<JSTaggedValue> numicValue(factory->NewFromASCII("numeric")); // test numeric
82     JSHandle<JSTaggedValue> weekDayValue(factory->NewFromASCII("short")); // test short
83     JSHandle<JSTaggedValue> dayPeriodValue(factory->NewFromASCII("long")); // test long
84     JSHandle<JSTaggedValue> hourCycleValue(factory->NewFromASCII("h24")); // test h24
85     JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII("UTC")); // test UTC
86 
87     JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(6); // 6 : 6 length
88     keyArray->Set(thread, 0, globalConst->GetHandledYearString()); // 0 : 0 first position
89     keyArray->Set(thread, 1, globalConst->GetHandledMonthString()); // 1 : 1 second position
90     keyArray->Set(thread, 2, globalConst->GetHandledDayString()); // 2 : 2 third position
91     keyArray->Set(thread, 3, globalConst->GetHandledHourString()); // 3 : 3 fourth position
92     keyArray->Set(thread, 4, globalConst->GetHandledMinuteString()); // 4 : 4 fifth position
93     keyArray->Set(thread, 5, globalConst->GetHandledSecondString()); // 5 : 5 sixth position
94 
95     uint32_t arrayLen = keyArray->GetLength();
96     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
97     for (uint32_t i = 0; i < arrayLen; i++) {
98         key.Update(keyArray->Get(thread, i));
99         JSObject::SetProperty(thread, optionsObj, key, numicValue);
100     }
101     JSObject::SetProperty(thread, optionsObj, weekDay, weekDayValue);
102     JSObject::SetProperty(thread, optionsObj, dayPeriod, dayPeriodValue);
103     JSObject::SetProperty(thread, optionsObj, hourCycle, hourCycleValue);
104     JSObject::SetProperty(thread, optionsObj, timeZone, timeZoneValue);
105     return optionsObj.GetTaggedValue();
106 }
107 
JSDateTimeFormatCreateWithLocaleTest(JSThread * thread,JSHandle<JSTaggedValue> & locale)108 static JSTaggedValue JSDateTimeFormatCreateWithLocaleTest(JSThread *thread, JSHandle<JSTaggedValue> &locale)
109 {
110     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
111     JSHandle<JSFunction> newTarget(env->GetDateTimeFormatFunction());
112     JSHandle<JSObject> optionsObj(thread, BuiltinsDateTimeOptionsSet(thread));
113 
114     JSHandle<JSTaggedValue> localesString = locale;
115     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
116     ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
117     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
118     ecmaRuntimeCallInfo->SetCallArg(0, localesString.GetTaggedValue());
119     ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
120 
121     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
122     JSTaggedValue result = BuiltinsDateTimeFormat::DateTimeFormatConstructor(ecmaRuntimeCallInfo);
123     EXPECT_TRUE(result.IsJSDateTimeFormat());
124     TestHelper::TearDownFrame(thread, prev);
125     return result;
126 }
127 
HWTEST_F_L0(BuiltinsDateTimeFormatTest,ResolvedOptions)128 HWTEST_F_L0(BuiltinsDateTimeFormatTest, ResolvedOptions)
129 {
130     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
131     auto globalConst = thread->GlobalConstants();
132     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("de-ID"));
133     JSHandle<JSDateTimeFormat> jsDateTimeFormat =
134        JSHandle<JSDateTimeFormat>(thread, JSDateTimeFormatCreateWithLocaleTest(thread, locale));
135 
136     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4);
137     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
138     ecmaRuntimeCallInfo->SetThis(jsDateTimeFormat.GetTaggedValue());
139 
140     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
141     JSTaggedValue result = BuiltinsDateTimeFormat::ResolvedOptions(ecmaRuntimeCallInfo);
142     TestHelper::TearDownFrame(thread, prev);
143 
144     JSHandle<JSTaggedValue> resultObj =
145         JSHandle<JSTaggedValue>(thread, JSTaggedValue(static_cast<JSTaggedType>(result.GetRawData())));
146     // judge whether the properties of the object are the same as those of jsdatetimeformat tag
147     JSHandle<JSTaggedValue> localeKey = globalConst->GetHandledLocaleString();
148     JSHandle<JSTaggedValue> localeValue(factory->NewFromASCII("de"));
149     EXPECT_EQ(JSTaggedValue::SameValue(
150         JSObject::GetProperty(thread, resultObj, localeKey).GetValue(), localeValue), true);
151     JSHandle<JSTaggedValue> timeZone = globalConst->GetHandledTimeZoneString();
152     JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII("UTC"));
153     EXPECT_EQ(JSTaggedValue::SameValue(
154         JSObject::GetProperty(thread, resultObj, timeZone).GetValue(), timeZoneValue), true);
155 }
156 
157 // SupportedLocalesOf("best fit")
HWTEST_F_L0(BuiltinsDateTimeFormatTest,SupportedLocalesOf_001)158 HWTEST_F_L0(BuiltinsDateTimeFormatTest, SupportedLocalesOf_001)
159 {
160     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
161     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("id-u-co-pinyin-de-ID"));
162 
163     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
164     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
165     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
166     ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
167     // set the tag is default value
168     ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue::Undefined());
169 
170     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
171     JSTaggedValue resultArr = BuiltinsDateTimeFormat::SupportedLocalesOf(ecmaRuntimeCallInfo);
172     TestHelper::TearDownFrame(thread, prev);
173 
174     JSHandle<JSArray> resultHandle(thread, resultArr);
175     JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
176     EXPECT_EQ(elements->GetLength(), 1U);
177 
178     JSHandle<EcmaString> resultStr(thread, elements->Get(0));
179     EXPECT_STREQ("id-u-co-pinyin-de-id", EcmaStringAccessor(resultStr).ToCString().c_str());
180 }
181 
182 // SupportedLocalesOf("look up")
HWTEST_F_L0(BuiltinsDateTimeFormatTest,SupportedLocalesOf_002)183 HWTEST_F_L0(BuiltinsDateTimeFormatTest, SupportedLocalesOf_002)
184 {
185     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
186     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
187 
188     JSHandle<JSTaggedValue> localeMatcherKey = thread->GlobalConstants()->GetHandledLocaleMatcherString();
189     JSHandle<JSTaggedValue> localeMatcherValue(factory->NewFromASCII("lookup"));
190     JSHandle<JSTaggedValue> locale(factory->NewFromASCII("id-u-co-pinyin-de-DE"));
191 
192     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
193     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
194     JSObject::SetProperty(thread, optionsObj, localeMatcherKey, localeMatcherValue);
195 
196     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
197     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
198     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
199     ecmaRuntimeCallInfo->SetCallArg(0, locale.GetTaggedValue());
200     ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
201 
202     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
203     JSTaggedValue resultArr = BuiltinsDateTimeFormat::SupportedLocalesOf(ecmaRuntimeCallInfo);
204     TestHelper::TearDownFrame(thread, prev);
205 
206     JSHandle<JSArray> resultHandle(thread, resultArr);
207     JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
208     EXPECT_EQ(elements->GetLength(), 1U);
209 
210     JSHandle<EcmaString> resultStr(thread, elements->Get(0));
211     EXPECT_STREQ("id-u-co-pinyin-de", EcmaStringAccessor(resultStr).ToCString().c_str());
212 }
213 
JSDateTime(JSThread * thread,JSTaggedValue & formatResult)214 static JSTaggedValue JSDateTime(JSThread *thread, JSTaggedValue &formatResult)
215 {
216     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
217     double days = 1665187200000;
218     // jsDate supports zero to eleven, the month should be added with one
219     JSHandle<JSFunction> jsFunction(thread, formatResult);
220     JSArray *jsArray =
221         JSArray::Cast(JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject());
222     JSHandle<JSObject> jsObject(thread, jsArray);
223     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(static_cast<double>(days)));
224     PropertyDescriptor desc(thread, JSHandle<JSTaggedValue>(jsFunction), true, true, true);
225     JSHandle<JSTaggedValue> joinKey(factory->NewFromASCII("join"));
226     JSArray::DefineOwnProperty(thread, jsObject, joinKey, desc);
227     auto ecmaRuntimeCallInfo2 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
228     ecmaRuntimeCallInfo2->SetFunction(JSTaggedValue::Undefined());
229     ecmaRuntimeCallInfo2->SetThis(jsObject.GetTaggedValue());
230     ecmaRuntimeCallInfo2->SetCallArg(0, value.GetTaggedValue());
231 
232     [[maybe_unused]] auto prev2 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo2);
233     JSTaggedValue result2 = BuiltinsArray::ToString(ecmaRuntimeCallInfo2);
234     TestHelper::TearDownFrame(thread, prev2);
235     return result2;
236 }
237 
JSDateTimeFormatConstructor(JSThread * thread,JSHandle<JSObject> & optionsObj,JSHandle<JSTaggedValue> & localesString)238 static JSTaggedValue JSDateTimeFormatConstructor(JSThread *thread, JSHandle<JSObject> &optionsObj,
239     JSHandle<JSTaggedValue> &localesString)
240 {
241     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
242     JSHandle<JSFunction> newTarget(env->GetDateTimeFormatFunction());
243 
244     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*newTarget), 8);
245     ecmaRuntimeCallInfo->SetFunction(newTarget.GetTaggedValue());
246     ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
247     ecmaRuntimeCallInfo->SetCallArg(0, localesString.GetTaggedValue());
248     ecmaRuntimeCallInfo->SetCallArg(1, optionsObj.GetTaggedValue());
249 
250     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
251     JSTaggedValue result = BuiltinsDateTimeFormat::DateTimeFormatConstructor(ecmaRuntimeCallInfo);
252     EXPECT_TRUE(result.IsJSDateTimeFormat());
253     TestHelper::TearDownFrame(thread, prev);
254     return result;
255 }
256 
JSDateTimeFormatForObject(JSThread * thread,JSTaggedValue & constructorResult)257 static JSTaggedValue JSDateTimeFormatForObject(JSThread *thread, JSTaggedValue &constructorResult)
258 {
259     JSHandle<JSDateTimeFormat> jsDateTimeFormat = JSHandle<JSDateTimeFormat>(thread, constructorResult);
260     auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
261     ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
262     ecmaRuntimeCallInfo1->SetThis(jsDateTimeFormat.GetTaggedValue());
263     ecmaRuntimeCallInfo1->SetCallArg(0, JSTaggedValue::Undefined());
264     [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
265     JSTaggedValue result1 = BuiltinsDateTimeFormat::Format(ecmaRuntimeCallInfo1);
266     TestHelper::TearDownFrame(thread, prev1);
267     return result1;
268 }
269 
JSDateTimeFormatForObj_001(JSThread * thread)270 static JSTaggedValue JSDateTimeFormatForObj_001(JSThread *thread)
271 {
272     auto globalConst = thread->GlobalConstants();
273     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
274     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
275     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
276     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
277 
278     JSHandle<JSTaggedValue> timeZoneName = globalConst->GetHandledTimeZoneNameString();
279     JSHandle<JSTaggedValue> localesString(factory->NewFromASCII("en-US"));
280     JSHandle<JSTaggedValue> digitValue(factory->NewFromASCII("2-digit"));
281     JSHandle<JSTaggedValue> timeZoneNameValue(factory->NewFromASCII("short"));
282 
283     JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(6); // 6 : 6 length
284     keyArray->Set(thread, 0, globalConst->GetHandledYearString()); // 0 : 0 first position
285     keyArray->Set(thread, 1, globalConst->GetHandledMonthString()); // 1 : 1 second position
286     keyArray->Set(thread, 2, globalConst->GetHandledDayString()); // 2 : 2 third position
287     keyArray->Set(thread, 3, globalConst->GetHandledHourString()); // 3 : 3 fourth position
288     keyArray->Set(thread, 4, globalConst->GetHandledMinuteString()); // 4 : 4 fifth position
289     keyArray->Set(thread, 5, globalConst->GetHandledSecondString()); // 5 : 5 sixth position
290     uint32_t arrayLen = keyArray->GetLength();
291     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
292     for (uint32_t i = 0; i < arrayLen; i++) {
293         key.Update(keyArray->Get(thread, i));
294         JSObject::SetProperty(thread, optionsObj, key, digitValue);
295     }
296     JSObject::SetProperty(thread, optionsObj, timeZoneName, timeZoneNameValue);
297     return optionsObj.GetTaggedValue();
298 }
299 
TimeOffset()300 static int TimeOffset()
301 {
302     // Get Sys time
303     time_t rt = time(nullptr);
304     // Convert Sys time to GMT time
305     tm gtm = *gmtime(&rt);
306     // Convert GMT time to Sys time
307     time_t gt = mktime(&gtm);
308     tm gtm2 = *localtime(&gt);
309     // Calculate time difference
310     int offset = ((rt - gt) + (gtm2.tm_isdst ? 3600 : 0)) / 60;
311     return offset;
312 }
313 
314 // DateTimeFormat_001
HWTEST_F_L0(BuiltinsDateTimeFormatTest,DateTimeFormat_001)315 HWTEST_F_L0(BuiltinsDateTimeFormatTest, DateTimeFormat_001)
316 {
317     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
318     JSHandle<JSTaggedValue> localesString(factory->NewFromASCII("en-US"));
319     auto jsObj = JSHandle<JSObject>(thread, JSDateTimeFormatForObj_001(thread));
320     auto constructorResult = JSDateTimeFormatConstructor(thread, jsObj, localesString);
321     auto formatResult = JSDateTimeFormatForObject(thread, constructorResult);
322     auto dtResult = JSDateTime(thread, formatResult);
323     JSHandle<EcmaString> resultStr(thread, dtResult);
324 
325     constexpr int shanghai = 480;
326     constexpr int americaRegina = -360;
327     constexpr int americaNewYork = -300;
328     constexpr int sysDefaultTimezone = -180; // america_argentina_Buenos_Aires
329     constexpr int utc = 0;
330     auto cstr = EcmaStringAccessor(resultStr).ToCString();
331     if (TimeOffset() == utc) {
332         if (cstr.find("GMT") != std::string::npos) {
333             EXPECT_STREQ("10/08/22, 12:00:00 AM GMT", cstr.c_str());
334         }
335         if (cstr.find("UTC") != std::string::npos) {
336             EXPECT_STREQ("10/08/22, 12:00:00 AM UTC", cstr.c_str());
337         }
338     }
339     if (TimeOffset() == shanghai) {
340         if (cstr.find("CST") != std::string::npos) {
341             EXPECT_STREQ("10/08/22, 08:00:00 AM CST", cstr.c_str());
342         }
343         if (cstr.find("GMT+8") != std::string::npos) {
344             EXPECT_STREQ("10/08/22, 08:00:00 AM GMT+8", cstr.c_str());
345         }
346     }
347     if (TimeOffset() == americaRegina) {
348         if (cstr.find("CST") != std::string::npos) {
349             EXPECT_STREQ("10/07/22, 06:00:00 PM CST", cstr.c_str());
350         }
351     }
352     if (TimeOffset() == americaNewYork) {
353         if (cstr.find("EST") != std::string::npos) {
354             EXPECT_STREQ("10/07/22, 06:00:00 PM EST", cstr.c_str());
355         }
356     }
357     if (TimeOffset() == sysDefaultTimezone) {
358         if (cstr.find("GMT-3") != std::string::npos) {
359             EXPECT_STREQ("10/07/22, 09:00:00 PM GMT-3", cstr.c_str());
360         }
361     }
362 }
363 
JSDateTimeFormatForObj_002(JSThread * thread)364 static JSTaggedValue JSDateTimeFormatForObj_002(JSThread *thread)
365 {
366     auto globalConst = thread->GlobalConstants();
367     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
368     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
369     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
370     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
371 
372     JSHandle<JSTaggedValue> timeZoneName = globalConst->GetHandledTimeZoneNameString();
373     JSHandle<JSTaggedValue> timeZone = globalConst->GetHandledTimeZoneString();
374     JSHandle<JSTaggedValue> numicValue(factory->NewFromASCII("numeric"));
375     JSHandle<JSTaggedValue> digitValue(factory->NewFromASCII("2-digit"));
376     JSHandle<JSTaggedValue> longValue(factory->NewFromASCII("long"));
377     JSHandle<JSTaggedValue> timeZoneNameValue(factory->NewFromASCII("short"));
378     JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII("UTC"));
379 
380     JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(6); // 6 : 6 length
381     keyArray->Set(thread, 0, globalConst->GetHandledYearString()); // 0 : 0 first position
382     keyArray->Set(thread, 1, globalConst->GetHandledMonthString()); // 1 : 1 second position
383     keyArray->Set(thread, 2, globalConst->GetHandledDayString()); // 2 : 2 third position
384     keyArray->Set(thread, 3, globalConst->GetHandledHourString()); // 3 : 3 fourth position
385     keyArray->Set(thread, 4, globalConst->GetHandledMinuteString()); // 4 : 4 fifth position
386     keyArray->Set(thread, 5, globalConst->GetHandledSecondString()); // 5 : 5 sixth position
387     uint32_t arrayLen = keyArray->GetLength();
388     uint32_t arrIndex[] = {0, 2};
389     uint32_t arrIndex2 = 1;
390     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
391     for (uint32_t i = 0; i < arrayLen; i++) {
392         key.Update(keyArray->Get(thread, i));
393         bool exists = std::count(std::begin(arrIndex), std::end(arrIndex), i) > 0;
394         if (exists) {
395             JSObject::SetProperty(thread, optionsObj, key, numicValue);
396         } else if (i == arrIndex2) {
397             JSObject::SetProperty(thread, optionsObj, key, longValue);
398         } else {
399             JSObject::SetProperty(thread, optionsObj, key, digitValue);
400         }
401     }
402     JSObject::SetProperty(thread, optionsObj, timeZoneName, timeZoneNameValue);
403     JSObject::SetProperty(thread, optionsObj, timeZone, timeZoneValue);
404     return optionsObj.GetTaggedValue();
405 }
406 
407 // DateTimeFormat_002
HWTEST_F_L0(BuiltinsDateTimeFormatTest,DateTimeFormat_002)408 HWTEST_F_L0(BuiltinsDateTimeFormatTest, DateTimeFormat_002)
409 {
410     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
411     JSHandle<JSTaggedValue> localesString(factory->NewFromASCII("zh-CN"));
412     auto jsObj = JSHandle<JSObject>(thread, JSDateTimeFormatForObj_002(thread));
413     auto constructorResult = JSDateTimeFormatConstructor(thread, jsObj, localesString);
414     auto formatResult = JSDateTimeFormatForObject(thread, constructorResult);
415     auto dtResult = JSDateTime(thread, formatResult);
416     JSHandle<EcmaString> resultStr(thread, dtResult);
417     EXPECT_STREQ("2022年10月8日 UTC 上午12:00:00", EcmaStringAccessor(resultStr).ToCString().c_str());
418 }
419 
420 // DateTimeFormat_003
HWTEST_F_L0(BuiltinsDateTimeFormatTest,DateTimeFormat_003)421 HWTEST_F_L0(BuiltinsDateTimeFormatTest, DateTimeFormat_003)
422 {
423     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
424     JSHandle<JSTaggedValue> localesString(factory->NewFromASCII("zh-CN"));
425 
426     auto jsObj = JSHandle<JSObject>(thread, JSDateTimeFormatForObj_002(thread));
427     auto constructorResult = JSDateTimeFormatConstructor(thread, jsObj, localesString);
428     JSHandle<JSDateTimeFormat> jsDateTimeFormat = JSHandle<JSDateTimeFormat>(thread, constructorResult);
429     auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
430     ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
431     ecmaRuntimeCallInfo->SetThis(jsDateTimeFormat.GetTaggedValue());
432     ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue::Undefined());
433 
434     [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
435     JSTaggedValue result = BuiltinsDateTimeFormat::FormatToParts(ecmaRuntimeCallInfo);
436     TestHelper::TearDownFrame(thread, prev);
437 
438     JSHandle<JSArray> resultHandle(thread, result);
439     JSHandle<TaggedArray> elements(thread, resultHandle->GetElements());
440     EXPECT_EQ(elements->GetLength(), 16U);
441 }
442 
443 // DateTimeFormat_004
HWTEST_F_L0(BuiltinsDateTimeFormatTest,DateTimeFormat_004)444 HWTEST_F_L0(BuiltinsDateTimeFormatTest, DateTimeFormat_004)
445 {
446     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
447     JSHandle<JSTaggedValue> localesString(factory->NewFromASCII("zh-CN"));
448     auto jsObj = JSHandle<JSObject>(thread, JSDateTimeFormatForObj_002(thread));
449     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
450     JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
451     JSHandle<JSObject> optionsObj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
452     JSHandle<JSTaggedValue> fullValue(factory->NewFromASCII("full"));
453     JSHandle<JSTaggedValue> falseValue(thread, JSTaggedValue(false));
454     JSHandle<JSTaggedValue> dateStyleValue(factory->NewFromASCII("dateStyle"));
455     JSHandle<JSTaggedValue> timeStyleeValue(factory->NewFromASCII("timeStyle"));
456     JSHandle<JSTaggedValue> hour12Value(factory->NewFromASCII("hour12"));
457     JSHandle<JSTaggedValue> timeZone(factory->NewFromASCII("timeZone"));
458     JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII("UTC"));
459     JSObject::SetProperty(thread, optionsObj, dateStyleValue, fullValue);
460     JSObject::SetProperty(thread, optionsObj, timeStyleeValue, fullValue);
461     JSObject::SetProperty(thread, optionsObj, hour12Value, falseValue);
462     JSObject::SetProperty(thread, optionsObj, timeZone, timeZoneValue);
463     auto constructorResult = JSDateTimeFormatConstructor(thread, optionsObj, localesString);
464     JSHandle<EcmaString> resultStr =
465         JSDateTimeFormat::FormatDateTime(thread, JSHandle<JSDateTimeFormat>(thread, constructorResult), 0.0);
466     EXPECT_STREQ("1970年1月1日星期四 协调世界时 00:00:00", EcmaStringAccessor(resultStr).ToCString().c_str());
467 }
468 } // namespace panda::test