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/intl/locale_helper.h"
17 #include "ecmascript/global_env.h"
18 #include "ecmascript/js_date.h"
19 #include "ecmascript/js_date_time_format.h"
20 #include "ecmascript/js_locale.h"
21 #include "ecmascript/tests/test_helper.h"
22
23 using namespace panda;
24 using namespace panda::ecmascript;
25 using namespace panda::ecmascript::base;
26 using LocaleHelper = panda::ecmascript::intl::LocaleHelper;
27
28 namespace panda::test {
29 class JSDateTimeFormatTest : public testing::Test {
30 public:
SetUpTestCase()31 static void SetUpTestCase()
32 {
33 GTEST_LOG_(INFO) << "SetUpTestCase";
34 }
35
TearDownTestCase()36 static void TearDownTestCase()
37 {
38 GTEST_LOG_(INFO) << "TearDownCase";
39 }
40
SetUp()41 void SetUp() override
42 {
43 JSRuntimeOptions options;
44 #if PANDA_TARGET_LINUX
45 // for consistency requirement, use ohos_icu4j/data as icu-data-path
46 options.SetIcuDataPath(ICU_PATH);
47 #endif
48 options.SetEnableForceGC(true);
49 instance = JSNApi::CreateEcmaVM(options);
50 instance->SetEnableForceGC(true);
51 ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
52 thread = instance->GetJSThread();
53 scope = new EcmaHandleScope(thread);
54 }
55
TearDown()56 void TearDown() override
57 {
58 TestHelper::DestroyEcmaVMWithScope(instance, scope);
59 }
60
61 EcmaVM *instance {nullptr};
62 EcmaHandleScope *scope {nullptr};
63 JSThread *thread {nullptr};
64 };
65
SetDateOptionsTest(JSThread * thread,JSHandle<JSObject> & optionsObj,std::map<std::string,std::string> & dateOptions)66 void SetDateOptionsTest(JSThread *thread, JSHandle<JSObject> &optionsObj,
67 std::map<std::string, std::string> &dateOptions)
68 {
69 auto vm = thread->GetEcmaVM();
70 auto factory = vm->GetFactory();
71 auto globalConst = thread->GlobalConstants();
72 // Date options keys.
73 JSHandle<JSTaggedValue> weekdayKey = globalConst->GetHandledWeekdayString();
74 JSHandle<JSTaggedValue> yearKey = globalConst->GetHandledYearString();
75 JSHandle<JSTaggedValue> monthKey = globalConst->GetHandledMonthString();
76 JSHandle<JSTaggedValue> dayKey = globalConst->GetHandledDayString();
77 // Date options values.
78 JSHandle<JSTaggedValue> weekdayValue(factory->NewFromASCII(dateOptions["weekday"].c_str()));
79 JSHandle<JSTaggedValue> yearValue(factory->NewFromASCII(dateOptions["year"].c_str()));
80 JSHandle<JSTaggedValue> monthValue(factory->NewFromASCII(dateOptions["month"].c_str()));
81 JSHandle<JSTaggedValue> dayValue(factory->NewFromASCII(dateOptions["day"].c_str()));
82 // Set date options.
83 JSObject::SetProperty(thread, optionsObj, weekdayKey, weekdayValue);
84 JSObject::SetProperty(thread, optionsObj, yearKey, yearValue);
85 JSObject::SetProperty(thread, optionsObj, monthKey, monthValue);
86 JSObject::SetProperty(thread, optionsObj, dayKey, dayValue);
87 }
88
SetTimeOptionsTest(JSThread * thread,JSHandle<JSObject> & optionsObj,std::map<std::string,std::string> & timeOptionsMap)89 void SetTimeOptionsTest(JSThread *thread, JSHandle<JSObject> &optionsObj,
90 std::map<std::string, std::string> &timeOptionsMap)
91 {
92 auto vm = thread->GetEcmaVM();
93 auto factory = vm->GetFactory();
94 auto globalConst = thread->GlobalConstants();
95 // Time options keys.
96 JSHandle<JSTaggedValue> dayPeriodKey = globalConst->GetHandledDayPeriodString();
97 JSHandle<JSTaggedValue> hourKey = globalConst->GetHandledHourString();
98 JSHandle<JSTaggedValue> minuteKey = globalConst->GetHandledMinuteString();
99 JSHandle<JSTaggedValue> secondKey = globalConst->GetHandledSecondString();
100 JSHandle<JSTaggedValue> fractionalSecondDigitsKey = globalConst->GetHandledFractionalSecondDigitsString();
101 // Time options values.
102 JSHandle<JSTaggedValue> dayPeriodValue(factory->NewFromASCII(timeOptionsMap["dayPeriod"].c_str()));
103 JSHandle<JSTaggedValue> hourValue(factory->NewFromASCII(timeOptionsMap["hour"].c_str()));
104 JSHandle<JSTaggedValue> minuteValue(factory->NewFromASCII(timeOptionsMap["minute"].c_str()));
105 JSHandle<JSTaggedValue> secondValue(factory->NewFromASCII(timeOptionsMap["second"].c_str()));
106 JSHandle<JSTaggedValue> fractionalSecondDigitsValue(
107 factory->NewFromASCII(timeOptionsMap["fractionalSecond"].c_str()));
108 // Set time options.
109 JSObject::SetProperty(thread, optionsObj, dayPeriodKey, dayPeriodValue);
110 JSObject::SetProperty(thread, optionsObj, hourKey, hourValue);
111 JSObject::SetProperty(thread, optionsObj, minuteKey, minuteValue);
112 JSObject::SetProperty(thread, optionsObj, secondKey, secondValue);
113 JSObject::SetProperty(thread, optionsObj, fractionalSecondDigitsKey, fractionalSecondDigitsValue);
114 }
115
116 /**
117 * @tc.name: GetIcuLocale & SetIcuLocale
118 * @tc.desc: Set and obtain localization labels compatible with ICU Libraries.
119 * @tc.type: FUNC
120 * @tc.require:
121 */
HWTEST_F_L0(JSDateTimeFormatTest,Set_Get_IcuLocale)122 HWTEST_F_L0(JSDateTimeFormatTest, Set_Get_IcuLocale)
123 {
124 auto vm = thread->GetEcmaVM();
125 auto factory = vm->GetFactory();
126 auto env = vm->GetGlobalEnv();
127 JSHandle<JSTaggedValue> ctor = env->GetDateTimeFormatFunction();
128 JSHandle<JSDateTimeFormat> dtf =
129 JSHandle<JSDateTimeFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
130
131 icu::Locale locale1("ko", "Kore", "KR");
132 JSDateTimeFormat::SetIcuLocale(thread, dtf, locale1, JSDateTimeFormat::FreeIcuLocale);
133 icu::Locale *resLocale1 = dtf->GetIcuLocale();
134 EXPECT_STREQ(resLocale1->getBaseName(), "ko_Kore_KR");
135
136 icu::Locale locale2("zh", "Hans", "Cn");
137 JSDateTimeFormat::SetIcuLocale(thread, dtf, locale2, JSDateTimeFormat::FreeIcuLocale);
138 icu::Locale *resLocale2 = dtf->GetIcuLocale();
139 EXPECT_STREQ(resLocale2->getBaseName(), "zh_Hans_CN");
140 }
141
142 /**
143 * @tc.name: SetIcuSimpleDateFormat & GetIcuSimpleDateFormat
144 * @tc.desc: Set and obtain a simple time and date format compatible with ICU Libraries.
145 * @tc.type: FUNC
146 * @tc.require:
147 */
HWTEST_F_L0(JSDateTimeFormatTest,Set_Get_IcuSimpleDateFormat)148 HWTEST_F_L0(JSDateTimeFormatTest, Set_Get_IcuSimpleDateFormat)
149 {
150 auto vm = thread->GetEcmaVM();
151 auto factory = vm->GetFactory();
152 auto env = vm->GetGlobalEnv();
153 const icu::UnicodeString timeZoneId("Asia/Shanghai");
154 icu::TimeZone *tz = icu::TimeZone::createTimeZone(timeZoneId);
155 icu::TimeZone::adoptDefault(tz);
156 JSHandle<JSTaggedValue> ctor = env->GetDateTimeFormatFunction();
157 JSHandle<JSDateTimeFormat> dtf =
158 JSHandle<JSDateTimeFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
159 UErrorCode status = UErrorCode::U_ZERO_ERROR;
160 icu::UnicodeString dateTime1("2022.05.25 11:09:34");
161 icu::UnicodeString dateTime2("2022.May.25 11:09:34");
162 icu::UnicodeString dateTime3("2022.May.25 AD 11:09:34 AM");
163
164 icu::UnicodeString pattern("yyyy.MM.dd HH:mm:ss");
165 icu::SimpleDateFormat sdf(pattern, status);
166 JSDateTimeFormat::SetIcuSimpleDateFormat(thread, dtf, sdf, JSDateTimeFormat::FreeSimpleDateFormat);
167 icu::SimpleDateFormat *resSdf = dtf->GetIcuSimpleDateFormat();
168 UDate timeStamp = resSdf->parse(dateTime1, status);
169 EXPECT_EQ(timeStamp, 1653448174000);
170 status = UErrorCode::U_ZERO_ERROR;
171 timeStamp = resSdf->parse(dateTime2, status);
172 EXPECT_EQ(timeStamp, 1653448174000);
173 status = UErrorCode::U_ZERO_ERROR;
174 timeStamp = resSdf->parse(dateTime3, status);
175 EXPECT_EQ(timeStamp, 0);
176
177 status = UErrorCode::U_ZERO_ERROR;
178 icu::UnicodeString pattern2("yyyyy.MMMMM.dd GGG hh:mm::ss aaa");
179 icu::SimpleDateFormat sdf2(pattern2, status);
180 JSDateTimeFormat::SetIcuSimpleDateFormat(thread, dtf, sdf2, JSDateTimeFormat::FreeSimpleDateFormat);
181 icu::SimpleDateFormat *resSdf2 = dtf->GetIcuSimpleDateFormat();
182 timeStamp = resSdf2->parse(dateTime1, status);
183 EXPECT_EQ(timeStamp, 0);
184 status = UErrorCode::U_ZERO_ERROR;
185 timeStamp = resSdf2->parse(dateTime2, status);
186 EXPECT_EQ(timeStamp, 0);
187 status = UErrorCode::U_ZERO_ERROR;
188 timeStamp = resSdf2->parse(dateTime3, status);
189 EXPECT_EQ(timeStamp, 1653448174000);
190 }
191
192 /**
193 * @tc.name: InitializeDateTimeFormat
194 * @tc.desc: Initialize the time and date format through localization label locales and options.
195 * Options can include year, month, day, hour, minute, second, time zone and weekday, etc.
196 * @tc.type: FUNC
197 * @tc.require:
198 */
HWTEST_F_L0(JSDateTimeFormatTest,InitializeDateTimeFormat)199 HWTEST_F_L0(JSDateTimeFormatTest, InitializeDateTimeFormat)
200 {
201 auto vm = thread->GetEcmaVM();
202 auto factory = vm->GetFactory();
203 auto env = vm->GetGlobalEnv();
204 // Create locales.
205 JSHandle<JSTaggedValue> localeCtor = env->GetLocaleFunction();
206 JSHandle<JSLocale> locales =
207 JSHandle<JSLocale>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(localeCtor), localeCtor));
208 icu::Locale icuLocale("zh", "Hans", "Cn", "calendar=chinese");
209 factory->NewJSIntlIcuData(locales, icuLocale, JSLocale::FreeIcuLocale);
210 // Create options.
211 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
212 JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
213 options = JSDateTimeFormat::ToDateTimeOptions(
214 thread, JSHandle<JSTaggedValue>::Cast(options), RequiredOption::ANY, DefaultsOption::ALL);
215 // Initialize DateTimeFormat.
216 JSHandle<JSTaggedValue> dtfCtor = env->GetDateTimeFormatFunction();
217 JSHandle<JSDateTimeFormat> dtf =
218 JSHandle<JSDateTimeFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dtfCtor), dtfCtor));
219 dtf = JSDateTimeFormat::InitializeDateTimeFormat(
220 thread, dtf, JSHandle<JSTaggedValue>::Cast(locales), JSHandle<JSTaggedValue>::Cast(options));
221
222 JSHandle<JSTaggedValue> localeTagVal(thread, dtf->GetLocale());
223 JSHandle<EcmaString> localeEcmaStr = JSHandle<EcmaString>::Cast(localeTagVal);
224 std::string localeStr = LocaleHelper::ConvertToStdString(localeEcmaStr);
225 EXPECT_STREQ(localeStr.c_str(), "zh-Hans-CN-u-ca-chinese");
226 }
227
228 /**
229 * @tc.name: ToDateTimeOptions
230 * @tc.desc: Empty or incomplete option objects are supplemented according to the required option and default option.
231 * @tc.type: FUNC
232 * @tc.require:
233 */
HWTEST_F_L0(JSDateTimeFormatTest,ToDateTimeOptions_001)234 HWTEST_F_L0(JSDateTimeFormatTest, ToDateTimeOptions_001)
235 {
236 auto vm = thread->GetEcmaVM();
237 auto factory = vm->GetFactory();
238 auto env = vm->GetGlobalEnv();
239 auto globalConst = thread->GlobalConstants();
240
241 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
242 JSHandle<JSTaggedValue> yearKey = globalConst->GetHandledYearString();
243 JSHandle<JSTaggedValue> monthKey = globalConst->GetHandledMonthString();
244 JSHandle<JSTaggedValue> dayKey = globalConst->GetHandledDayString();
245 JSHandle<JSTaggedValue> hourKey = globalConst->GetHandledHourString();
246 JSHandle<JSTaggedValue> minuteKey = globalConst->GetHandledMinuteString();
247 JSHandle<JSTaggedValue> secondKey = globalConst->GetHandledSecondString();
248
249 // When the option value is blank, it will be set according to the default option,
250 // including the year, month, day, hour, minute and second, and the values are all numeric.
251 JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
252 options = JSDateTimeFormat::ToDateTimeOptions(
253 thread, JSHandle<JSTaggedValue>::Cast(options), RequiredOption::ANY, DefaultsOption::ALL); // test "ALL"
254 auto yearEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, yearKey).GetValue());
255 EXPECT_STREQ(LocaleHelper::ConvertToStdString(yearEcmaStr).c_str(), "numeric");
256 auto monthEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, monthKey).GetValue());
257 EXPECT_STREQ(LocaleHelper::ConvertToStdString(monthEcmaStr).c_str(), "numeric");
258 auto dayEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, dayKey).GetValue());
259 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dayEcmaStr).c_str(), "numeric");
260 auto hourEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, hourKey).GetValue());
261 EXPECT_STREQ(LocaleHelper::ConvertToStdString(hourEcmaStr).c_str(), "numeric");
262 auto minuteEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, minuteKey).GetValue());
263 EXPECT_STREQ(LocaleHelper::ConvertToStdString(minuteEcmaStr).c_str(), "numeric");
264 auto secondEcmaStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, secondKey).GetValue());
265 EXPECT_STREQ(LocaleHelper::ConvertToStdString(secondEcmaStr).c_str(), "numeric");
266 }
267
HWTEST_F_L0(JSDateTimeFormatTest,ToDateTimeOptions_002)268 HWTEST_F_L0(JSDateTimeFormatTest, ToDateTimeOptions_002)
269 {
270 auto vm = thread->GetEcmaVM();
271 auto factory = vm->GetFactory();
272 auto env = vm->GetGlobalEnv();
273 auto globalConst = thread->GlobalConstants();
274
275 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
276 JSHandle<JSTaggedValue> weekdayKey = globalConst->GetHandledWeekdayString();
277 JSHandle<JSTaggedValue> yearKey = globalConst->GetHandledYearString();
278 JSHandle<JSTaggedValue> monthKey = globalConst->GetHandledMonthString();
279 JSHandle<JSTaggedValue> dayKey = globalConst->GetHandledDayString();
280 JSHandle<JSTaggedValue> dayPeriodKey = globalConst->GetHandledDayPeriodString();
281 JSHandle<JSTaggedValue> hourKey = globalConst->GetHandledHourString();
282 JSHandle<JSTaggedValue> minuteKey = globalConst->GetHandledMinuteString();
283 JSHandle<JSTaggedValue> secondKey = globalConst->GetHandledSecondString();
284 JSHandle<JSTaggedValue> fracSecKey = globalConst->GetHandledFractionalSecondDigitsString();
285
286 // When the option value is not empty, it will be set according to the required options.
287 JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
288 std::map<std::string, std::string> dateOptionsMap {
289 { "weekday", "narrow" },
290 { "year", "2-digit" },
291 { "month", "2-digit" },
292 { "day", "2-digit" }
293 };
294 std::map<std::string, std::string> timeOptionsMap {
295 { "dayPeriod", "narrow" },
296 { "hour", "2-digit" },
297 { "minute", "2-digit" },
298 { "second", "2-digit" },
299 { "fractionalSecond", "1" }
300 };
301 SetDateOptionsTest(thread, options, dateOptionsMap);
302 SetTimeOptionsTest(thread, options, timeOptionsMap);
303 options = JSDateTimeFormat::ToDateTimeOptions(
304 thread, JSHandle<JSTaggedValue>::Cast(options), RequiredOption::ANY, DefaultsOption::ALL); // test "ANY"
305 auto weekdayStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, weekdayKey).GetValue());
306 EXPECT_STREQ(LocaleHelper::ConvertToStdString(weekdayStr).c_str(), "narrow");
307 auto yearStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, yearKey).GetValue());
308 EXPECT_STREQ(LocaleHelper::ConvertToStdString(yearStr).c_str(), "2-digit");
309 auto monthStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, monthKey).GetValue());
310 EXPECT_STREQ(LocaleHelper::ConvertToStdString(monthStr).c_str(), "2-digit");
311 auto dayStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, dayKey).GetValue());
312 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dayStr).c_str(), "2-digit");
313
314 auto dayPeriodStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, dayPeriodKey).GetValue());
315 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dayPeriodStr).c_str(), "narrow");
316 auto hourStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, hourKey).GetValue());
317 EXPECT_STREQ(LocaleHelper::ConvertToStdString(hourStr).c_str(), "2-digit");
318 auto minuteStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, minuteKey).GetValue());
319 EXPECT_STREQ(LocaleHelper::ConvertToStdString(minuteStr).c_str(), "2-digit");
320 auto secondStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, secondKey).GetValue());
321 EXPECT_STREQ(LocaleHelper::ConvertToStdString(secondStr).c_str(), "2-digit");
322 auto fracSecStr = JSHandle<EcmaString>::Cast(JSObject::GetProperty(thread, options, fracSecKey).GetValue());
323 EXPECT_STREQ(LocaleHelper::ConvertToStdString(fracSecStr).c_str(), "1");
324 }
325
CreateDateTimeFormatTest(JSThread * thread,icu::Locale icuLocale,JSHandle<JSObject> options)326 JSHandle<JSDateTimeFormat> CreateDateTimeFormatTest(JSThread *thread, icu::Locale icuLocale, JSHandle<JSObject> options)
327 {
328 auto vm = thread->GetEcmaVM();
329 auto factory = vm->GetFactory();
330 auto env = vm->GetGlobalEnv();
331
332 JSHandle<JSTaggedValue> localeCtor = env->GetLocaleFunction();
333 JSHandle<JSTaggedValue> dtfCtor = env->GetDateTimeFormatFunction();
334 JSHandle<JSLocale> locales =
335 JSHandle<JSLocale>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(localeCtor), localeCtor));
336 JSHandle<JSDateTimeFormat> dtf =
337 JSHandle<JSDateTimeFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dtfCtor), dtfCtor));
338
339 JSHandle<JSTaggedValue> optionsVal = JSHandle<JSTaggedValue>::Cast(options);
340 factory->NewJSIntlIcuData(locales, icuLocale, JSLocale::FreeIcuLocale);
341 dtf = JSDateTimeFormat::InitializeDateTimeFormat(thread, dtf, JSHandle<JSTaggedValue>::Cast(locales), optionsVal);
342 return dtf;
343 }
344 /**
345 * @tc.name: FormatDateTime
346 * @tc.desc: Convert floating-point timestamp to fixed format time date through time date format.
347 * @tc.type: FUNC
348 * @tc.require:
349 */
HWTEST_F_L0(JSDateTimeFormatTest,FormatDateTime_001)350 HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_001)
351 {
352 auto vm = thread->GetEcmaVM();
353 auto factory = vm->GetFactory();
354 auto env = vm->GetGlobalEnv();
355 auto globalConst = thread->GlobalConstants();
356
357 icu::Locale icuLocale("zh", "Hans", "Cn");
358 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
359 JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
360 JSHandle<JSTaggedValue> hourCycleKey = globalConst->GetHandledHourCycleString();
361 JSHandle<JSTaggedValue> hourCycleValue(factory->NewFromASCII("h12"));
362 JSHandle<JSTaggedValue> timeZoneKey = globalConst->GetHandledTimeZoneString();
363 JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII("ETC/GMT-8"));
364 JSObject::SetProperty(thread, options, timeZoneKey, timeZoneValue);
365 JSObject::SetProperty(thread, options, hourCycleKey, hourCycleValue);
366 JSHandle<JSDateTimeFormat> dtf = CreateDateTimeFormatTest(thread, icuLocale, options);
367
368 double timeStamp1 = 1653448174000; // test "2022-05-25 11:09:34.000"
369 double timeStamp2 = 1653921012999; // test "2022-05-30 22:30:12.999"
370
371 // When the option is blank, the default format is "yyyy/MM/dd", the year, month and day are all numeric,
372 // because the default option in initialization is "DefaultsOption::DATE".
373 JSHandle<EcmaString> dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1);
374 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25");
375 JSHandle<EcmaString> dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2);
376 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr2).c_str(), "2022/5/30");
377 }
378
HWTEST_F_L0(JSDateTimeFormatTest,FormatDateTime_002)379 HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_002)
380 {
381 auto vm = thread->GetEcmaVM();
382 auto factory = vm->GetFactory();
383 auto env = vm->GetGlobalEnv();
384 auto globalConst = thread->GlobalConstants();
385
386 icu::Locale icuLocale("zh", "Hans", "Cn");
387 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
388 JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
389 JSHandle<JSTaggedValue> hourCycleKey = globalConst->GetHandledHourCycleString();
390 JSHandle<JSTaggedValue> hourCycleValue(factory->NewFromASCII("h12"));
391 JSHandle<JSTaggedValue> timeZoneKey = globalConst->GetHandledTimeZoneString();
392 JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII("ETC/GMT-8"));
393 JSObject::SetProperty(thread, options, timeZoneKey, timeZoneValue);
394 JSObject::SetProperty(thread, options, hourCycleKey, hourCycleValue);
395 options = JSDateTimeFormat::ToDateTimeOptions(
396 thread, JSHandle<JSTaggedValue>::Cast(options), RequiredOption::ANY, DefaultsOption::ALL);
397 JSHandle<JSDateTimeFormat> dtf = CreateDateTimeFormatTest(thread, icuLocale, options);
398
399 double timeStamp1 = 1653448174000; // test "2022-05-25 11:09:34.000"
400 double timeStamp2 = 1653921012999; // test "2022-05-30 22:30:12.999"
401
402 // Format to include all options by "DefaultsOption::ALL".
403 JSHandle<EcmaString> dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1);
404 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25 上午11:09:34");
405 JSHandle<EcmaString> dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2);
406 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr2).c_str(), "2022/5/30 下午10:30:12");
407 }
408
HWTEST_F_L0(JSDateTimeFormatTest,FormatDateTime_003)409 HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_003)
410 {
411 auto vm = thread->GetEcmaVM();
412 auto factory = vm->GetFactory();
413 auto env = vm->GetGlobalEnv();
414 auto globalConst = thread->GlobalConstants();
415
416 icu::Locale icuLocale("zh", "Hans", "Cn");
417 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
418 JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
419 JSHandle<JSTaggedValue> hourCycleKey = globalConst->GetHandledHourCycleString();
420 JSHandle<JSTaggedValue> hourCycleValue(factory->NewFromASCII("h12"));
421 JSHandle<JSTaggedValue> timeZoneKey = globalConst->GetHandledTimeZoneString();
422 JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII("ETC/GMT-8"));
423 JSObject::SetProperty(thread, options, timeZoneKey, timeZoneValue);
424 JSObject::SetProperty(thread, options, hourCycleKey, hourCycleValue);
425
426 // Set custom date time format.
427 std::map<std::string, std::string> dateOptionsMap {
428 { "weekday", "long" },
429 { "year", "2-digit" },
430 { "month", "2-digit" },
431 { "day", "2-digit" }
432 };
433 std::map<std::string, std::string> timeOptionsMap {
434 { "dayPeriod", "long" },
435 { "hour", "2-digit" },
436 { "minute", "2-digit" },
437 { "second", "2-digit" },
438 { "fractionalSecond", "3" }
439 };
440 SetDateOptionsTest(thread, options, dateOptionsMap);
441 SetTimeOptionsTest(thread, options, timeOptionsMap);
442 options = JSDateTimeFormat::ToDateTimeOptions(
443 thread, JSHandle<JSTaggedValue>::Cast(options), RequiredOption::ANY, DefaultsOption::ALL);
444 JSHandle<JSDateTimeFormat> dtf = CreateDateTimeFormatTest(thread, icuLocale, options);
445
446 double timeStamp1 = 1653448174000; // test "2022-05-25 11:09:34.000"
447 double timeStamp2 = 1653921012999; // test "2022-05-30 22:30:12.999"
448
449 JSHandle<EcmaString> dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1);
450 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr1).c_str(), "22年05月25日星期三 上午11:09:34.000");
451 JSHandle<EcmaString> dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2);
452 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr2).c_str(), "22年05月30日星期一 晚上10:30:12.999");
453 }
454
HWTEST_F_L0(JSDateTimeFormatTest,FormatDateTime_004)455 HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_004)
456 {
457 auto vm = thread->GetEcmaVM();
458 auto factory = vm->GetFactory();
459 auto env = vm->GetGlobalEnv();
460 auto globalConst = thread->GlobalConstants();
461
462 icu::Locale icuLocale("en", "Latn", "US");
463 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
464 JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
465 JSHandle<JSTaggedValue> hourCycleKey = globalConst->GetHandledHourCycleString();
466 JSHandle<JSTaggedValue> hourCycleValue(factory->NewFromASCII("h12"));
467 JSHandle<JSTaggedValue> timeZoneKey = globalConst->GetHandledTimeZoneString();
468 JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII("ETC/GMT-8"));
469 JSObject::SetProperty(thread, options, timeZoneKey, timeZoneValue);
470 JSObject::SetProperty(thread, options, hourCycleKey, hourCycleValue);
471
472 // Set custom date time format.
473 std::map<std::string, std::string> dateOptionsMap {
474 { "weekday", "long" },
475 { "year", "2-digit" },
476 { "month", "2-digit" },
477 { "day", "2-digit" }
478 };
479 std::map<std::string, std::string> timeOptionsMap {
480 { "dayPeriod", "long" },
481 { "hour", "2-digit" },
482 { "minute", "2-digit" },
483 { "second", "2-digit" },
484 { "fractionalSecond", "3" }
485 };
486 SetDateOptionsTest(thread, options, dateOptionsMap);
487 SetTimeOptionsTest(thread, options, timeOptionsMap);
488 options = JSDateTimeFormat::ToDateTimeOptions(
489 thread, JSHandle<JSTaggedValue>::Cast(options), RequiredOption::ANY, DefaultsOption::ALL);
490 JSHandle<JSDateTimeFormat> dtf = CreateDateTimeFormatTest(thread, icuLocale, options);
491
492 double timeStamp1 = 1653448174000; // test "2022-05-25 11:09:34.000"
493 double timeStamp2 = 1653921012999; // test "2022-05-30 22:30:12.999"
494
495 JSHandle<EcmaString> dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1);
496 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr1).c_str(),
497 "Wednesday, 05/25/22, 11:09:34.000 in the morning");
498 JSHandle<EcmaString> dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2);
499 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr2).c_str(),
500 "Monday, 05/30/22, 10:30:12.999 at night");
501 }
502
GetDateTimePartStringTest(JSThread * thread,JSHandle<JSTaggedValue> key,JSHandle<JSTaggedValue> part)503 std::string GetDateTimePartStringTest(JSThread *thread, JSHandle<JSTaggedValue> key, JSHandle<JSTaggedValue> part)
504 {
505 JSHandle<JSObject> partObj = JSHandle<JSObject>::Cast(part);
506 JSHandle<JSTaggedValue> partValue = JSObject::GetProperty(thread, partObj, key).GetValue();
507 JSHandle<EcmaString> partEcmaStr = JSHandle<EcmaString>::Cast(partValue);
508 std::string partStr = LocaleHelper::ConvertToStdString(partEcmaStr);
509 return partStr;
510 }
511
512 /**
513 * @tc.name: FormatDateTimeToParts
514 * @tc.desc: Convert floating-point timestamp to fixed format time date through time date format.
515 * The "FormatDateTimeToParts" method converts the output result into an array containing various time and
516 * date attributes.
517 * @tc.type: FUNC
518 * @tc.require:
519 */
HWTEST_F_L0(JSDateTimeFormatTest,FormatDateTimeToParts_001)520 HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTimeToParts_001)
521 {
522 auto vm = thread->GetEcmaVM();
523 auto factory = vm->GetFactory();
524 auto env = vm->GetGlobalEnv();
525 auto globalConst = thread->GlobalConstants();
526
527 JSHandle<JSTaggedValue> typeKey = globalConst->GetHandledTypeString();
528 JSHandle<JSTaggedValue> valueKey = globalConst->GetHandledValueString();
529
530 icu::Locale icuLocale("zh", "Hans", "Cn");
531 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
532 JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
533 JSHandle<JSTaggedValue> hourCycleKey = globalConst->GetHandledHourCycleString();
534 JSHandle<JSTaggedValue> hourCycleValue(factory->NewFromASCII("h12"));
535 JSHandle<JSTaggedValue> timeZoneKey = globalConst->GetHandledTimeZoneString();
536 JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII("ETC/GMT-8"));
537 JSObject::SetProperty(thread, options, timeZoneKey, timeZoneValue);
538 JSObject::SetProperty(thread, options, hourCycleKey, hourCycleValue);
539 JSHandle<JSDateTimeFormat> dtf = CreateDateTimeFormatTest(thread, icuLocale, options);
540
541 double timeStamp = 1653448174123; // test "2022-05-25 11:09:34.123"
542 // Use default date time format and format date and time to parts.
543 JSHandle<EcmaString> dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp);
544 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25");
545 JSHandle<JSArray> dateTimeArray1 = JSDateTimeFormat::FormatDateTimeToParts(thread, dtf, timeStamp);
546 auto year = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray1), 0).GetValue();
547 auto literal1 = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray1), 1).GetValue();
548 auto month = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray1), 2).GetValue();
549 auto literal2 = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray1), 3).GetValue();
550 auto day = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray1), 4).GetValue();
551 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, year).c_str(), "year");
552 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, year).c_str(), "2022");
553 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal1).c_str(), "literal");
554 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal1).c_str(), "/");
555 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, month).c_str(), "month");
556 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, month).c_str(), "5");
557 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal2).c_str(), "literal");
558 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal2).c_str(), "/");
559 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, day).c_str(), "day");
560 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, day).c_str(), "25");
561 }
562
HWTEST_F_L0(JSDateTimeFormatTest,FormatDateTimeToParts_002)563 HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTimeToParts_002)
564 {
565 auto vm = thread->GetEcmaVM();
566 auto factory = vm->GetFactory();
567 auto env = vm->GetGlobalEnv();
568 auto globalConst = thread->GlobalConstants();
569
570 JSHandle<JSTaggedValue> typeKey = globalConst->GetHandledTypeString();
571 JSHandle<JSTaggedValue> valueKey = globalConst->GetHandledValueString();
572 icu::Locale icuLocale("zh", "Hans", "Cn");
573 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
574 JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
575 JSHandle<JSTaggedValue> hourCycleKey = globalConst->GetHandledHourCycleString();
576 JSHandle<JSTaggedValue> hourCycleValue(factory->NewFromASCII("h12"));
577 JSHandle<JSTaggedValue> timeZoneKey = globalConst->GetHandledTimeZoneString();
578 JSHandle<JSTaggedValue> timeZoneValue(factory->NewFromASCII("ETC/GMT-8"));
579 JSObject::SetProperty(thread, options, timeZoneKey, timeZoneValue);
580 JSObject::SetProperty(thread, options, hourCycleKey, hourCycleValue);
581
582 double timeStamp = 1653448174123; // test "2022-05-25 11:09:34.123"
583 // Set custom date time format and format date and time to parts.
584 std::map<std::string, std::string> dateOptionsMap {
585 { "weekday", "long" },
586 { "year", "2-digit" },
587 { "month", "2-digit" },
588 { "day", "2-digit" }
589 };
590 std::map<std::string, std::string> timeOptionsMap {
591 { "dayPeriod", "long" },
592 { "hour", "2-digit" },
593 { "minute", "2-digit" },
594 { "second", "2-digit" },
595 { "fractionalSecond", "3" }
596 };
597 SetDateOptionsTest(thread, options, dateOptionsMap);
598 SetTimeOptionsTest(thread, options, timeOptionsMap);
599 options = JSDateTimeFormat::ToDateTimeOptions(
600 thread, JSHandle<JSTaggedValue>::Cast(options), RequiredOption::ANY, DefaultsOption::ALL);
601 JSHandle<JSDateTimeFormat> dtf = CreateDateTimeFormatTest(thread, icuLocale, options);
602 JSHandle<EcmaString> dateTimeEcamStr = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp);
603 EXPECT_STREQ(LocaleHelper::ConvertToStdString(dateTimeEcamStr).c_str(), "22年05月25日星期三 上午11:09:34.123");
604
605 JSHandle<JSArray> dateTimeArray = JSDateTimeFormat::FormatDateTimeToParts(thread, dtf, timeStamp);
606 auto year = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 0).GetValue();
607 auto literal1 = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 1).GetValue();
608 auto month = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 2).GetValue();
609 auto literal2 = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 3).GetValue();
610 auto day = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 4).GetValue();
611 auto literal3 = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 5).GetValue();
612 auto weekday = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 6).GetValue();
613 auto literal4 = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 7).GetValue();
614 auto dayPeriod = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 8).GetValue();
615 auto hour = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 9).GetValue();
616 auto literal5 = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 10).GetValue();
617 auto minute = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 11).GetValue();
618 auto literal6 = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 12).GetValue();
619 auto second = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 13).GetValue();
620 auto literal7 = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 14).GetValue();
621 auto fracSec = JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>::Cast(dateTimeArray), 15).GetValue();
622 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, year).c_str(), "year");
623 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, year).c_str(), "22");
624 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal1).c_str(), "literal");
625 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal1).c_str(), "年");
626 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, month).c_str(), "month");
627 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, month).c_str(), "05");
628 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal2).c_str(), "literal");
629 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal2).c_str(), "月");
630 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, day).c_str(), "day");
631 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, day).c_str(), "25");
632 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal3).c_str(), "literal");
633 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal3).c_str(), "日");
634 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, weekday).c_str(), "weekday");
635 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, weekday).c_str(), "星期三");
636 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal4).c_str(), "literal");
637 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal4).c_str(), " ");
638 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, dayPeriod).c_str(), "dayPeriod");
639 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, dayPeriod).c_str(), "上午");
640 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, hour).c_str(), "hour");
641 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, hour).c_str(), "11");
642 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal5).c_str(), "literal");
643 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal5).c_str(), ":");
644 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, minute).c_str(), "minute");
645 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, minute).c_str(), "09");
646 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal6).c_str(), "literal");
647 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal6).c_str(), ":");
648 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, second).c_str(), "second");
649 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, second).c_str(), "34");
650 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal7).c_str(), "literal");
651 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal7).c_str(), ".");
652 EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, fracSec).c_str(), "fractionalSecond");
653 EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, fracSec).c_str(), "123");
654 }
655 /**
656 * @tc.name: GainAvailableLocales
657 * @tc.desc: Get the available localized label array. If the global time date localized label is not set, return an
658 * array containing all available labels. Otherwise, return an array containing self-defined labels.
659 * @tc.type: FUNC
660 * @tc.require:
661 */
HWTEST_F_L0(JSDateTimeFormatTest,GainAvailableLocales)662 HWTEST_F_L0(JSDateTimeFormatTest, GainAvailableLocales)
663 {
664 auto vm = thread->GetEcmaVM();
665 auto factory = vm->GetFactory();
666 auto env = vm->GetGlobalEnv();
667
668 // The date and time format locales is not initialized,
669 // then get all available locales and save them in a 'TaggedArray'.
670 JSHandle<JSTaggedValue> dateTimeFormatLocales = env->GetDateTimeFormatLocales();
671 EXPECT_EQ(dateTimeFormatLocales.GetTaggedValue(), JSTaggedValue::Undefined());
672
673 const char *key = "calendar";
674 const char *path = nullptr;
675 std::vector<std::string> availableStringLocales = intl::LocaleHelper::GetAvailableLocales(thread, key, path);
676 JSHandle<TaggedArray> availableLocales = JSLocale::ConstructLocaleList(thread, availableStringLocales);
677 env->SetDateTimeFormatLocales(thread, availableLocales);
678 JSHandle<TaggedArray> gainLocales1 = JSDateTimeFormat::GainAvailableLocales(thread);
679 EXPECT_EQ(JSHandle<JSTaggedValue>::Cast(gainLocales1).GetTaggedValue().GetRawData(),
680 JSHandle<JSTaggedValue>::Cast(availableLocales).GetTaggedValue().GetRawData());
681
682 // The date and time format locales has already been initialized,
683 // then get custom locale and save it in a 'TaggedArray'.
684 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
685 JSHandle<JSTaggedValue> localeCtor = env->GetLocaleFunction();
686 JSHandle<JSTaggedValue> dtfCtor = env->GetDateTimeFormatFunction();
687
688 JSHandle<JSLocale> locales =
689 JSHandle<JSLocale>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(localeCtor), localeCtor));
690 icu::Locale icuLocale("zh", "Hans", "Cn", "calendar=chinese");
691 factory->NewJSIntlIcuData(locales, icuLocale, JSLocale::FreeIcuLocale);
692 JSHandle<JSObject> options = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
693 options = JSDateTimeFormat::ToDateTimeOptions(
694 thread, JSHandle<JSTaggedValue>::Cast(options), RequiredOption::ANY, DefaultsOption::ALL);
695 JSHandle<JSDateTimeFormat> dtf =
696 JSHandle<JSDateTimeFormat>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(dtfCtor), dtfCtor));
697 dtf = JSDateTimeFormat::InitializeDateTimeFormat(
698 thread, dtf, JSHandle<JSTaggedValue>::Cast(locales), JSHandle<JSTaggedValue>::Cast(options));
699
700 JSHandle<JSTaggedValue> localeTagVal(thread, dtf->GetLocale());
701 JSHandle<TaggedArray> localesTagArr = factory->NewTaggedArray(1);
702 localesTagArr->Set(thread, 0, localeTagVal);
703 env->SetDateTimeFormatLocales(thread, localesTagArr);
704 JSHandle<TaggedArray> gainLocales2 = JSDateTimeFormat::GainAvailableLocales(thread);
705 EXPECT_EQ(gainLocales2->GetLength(), 1U);
706 EXPECT_STREQ(EcmaStringAccessor(gainLocales2->Get(0)).ToCString().c_str(),
707 "zh-Hans-CN-u-ca-chinese");
708 }
709 } // namespace panda::test
710