1 /*
2 * Copyright (c) 2025 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 #include "intl_date_time_format_addon.h"
16
17 #include <chrono>
18 #include <unordered_set>
19 #include "error_util.h"
20 #include "i18n_hilog.h"
21 #include "intl_date_time_format.h"
22 #include "js_utils.h"
23 #include "utils.h"
24
25 namespace OHOS {
26 namespace Global {
27 namespace I18n {
28 static thread_local napi_ref* g_IntlDateTimeFormatConstructor = nullptr;
29 static constexpr int NUMBER_OF_PARAMETER = 2;
30
IntlDateTimeFormatAddon()31 IntlDateTimeFormatAddon::IntlDateTimeFormatAddon()
32 {
33 }
34
~IntlDateTimeFormatAddon()35 IntlDateTimeFormatAddon::~IntlDateTimeFormatAddon()
36 {
37 }
38
Destructor(napi_env,void * nativeObject,void *)39 void IntlDateTimeFormatAddon::Destructor(napi_env /* env */, void* nativeObject, void* /* hint */)
40 {
41 if (!nativeObject) {
42 return;
43 }
44 delete reinterpret_cast<IntlDateTimeFormatAddon*>(nativeObject);
45 nativeObject = nullptr;
46 }
47
InitIntlDateTimeFormat(napi_env env,napi_value exports)48 napi_value IntlDateTimeFormatAddon::InitIntlDateTimeFormat(napi_env env, napi_value exports)
49 {
50 napi_property_descriptor properties[] = {
51 DECLARE_NAPI_FUNCTION("format", Format),
52 DECLARE_NAPI_FUNCTION("formatToParts", FormatToParts),
53 DECLARE_NAPI_FUNCTION("formatRange", FormatRange),
54 DECLARE_NAPI_FUNCTION("formatRangeToParts", FormatRangeToParts),
55 DECLARE_NAPI_FUNCTION("resolvedOptions", ResolvedOptions),
56 DECLARE_NAPI_STATIC_FUNCTION("supportedLocalesOf", SupportedLocalesOf),
57 };
58
59 napi_value constructor = nullptr;
60 napi_status status = napi_define_class(env, "DateTimeFormat", NAPI_AUTO_LENGTH, IntlDateTimeFormatConstructor,
61 nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
62 if (status != napi_ok) {
63 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::InitIntlDateTimeFormat: Define class failed when InitIntlLocale.");
64 return nullptr;
65 }
66
67 status = napi_set_named_property(env, exports, "DateTimeFormat", constructor);
68 if (status != napi_ok) {
69 HILOG_ERROR_I18N(
70 "IntlDateTimeFormatAddon::InitIntlDateTimeFormat: Set property failed when InitIntlDateTimeFormat.");
71 return nullptr;
72 }
73
74 g_IntlDateTimeFormatConstructor = new (std::nothrow) napi_ref;
75 if (!g_IntlDateTimeFormatConstructor) {
76 HILOG_ERROR_I18N(
77 "IntlDateTimeFormatAddon::InitIntlDateTimeFormat: Failed to create DateTimeFormat ref at init.");
78 return nullptr;
79 }
80
81 status = napi_create_reference(env, constructor, 1, g_IntlDateTimeFormatConstructor);
82 if (status != napi_ok) {
83 HILOG_ERROR_I18N(
84 "IntlDateTimeFormatAddon::InitIntlDateTimeFormat: Failed to create reference g_IntlLocaleConstructor.");
85 return nullptr;
86 }
87
88 return exports;
89 }
90
IntlDateTimeFormatConstructor(napi_env env,napi_callback_info info)91 napi_value IntlDateTimeFormatAddon::IntlDateTimeFormatConstructor(napi_env env, napi_callback_info info)
92 {
93 size_t argc = 2;
94 napi_value argv[2] = { nullptr };
95 napi_value thisVar = nullptr;
96 void *data = nullptr;
97 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
98 if (status != napi_ok) {
99 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::IntlDateTimeFormatConstructor: Get cb info failed.");
100 return nullptr;
101 }
102
103 napi_value new_target;
104 status = napi_get_new_target(env, info, &new_target);
105 if (status == napi_pending_exception || new_target == nullptr) {
106 return CreateDateTimeFormatWithoutNew(env, argc, argv);
107 } else if (status != napi_ok) {
108 return nullptr;
109 }
110
111 std::vector<std::string> localeTags;
112 if (argc > 0) {
113 int32_t code = 0;
114 std::vector<std::string> localeArray = JSUtils::GetLocaleArray(env, argv[0], code);
115 localeTags.assign(localeArray.begin(), localeArray.end());
116 }
117
118 std::unordered_map<std::string, std::string> configs;
119 if (argc > 1) {
120 ParseConfigs(env, argv[1], configs);
121 }
122 IntlDateTimeFormatAddon* obj = new (std::nothrow) IntlDateTimeFormatAddon();
123 if (obj == nullptr) {
124 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::IntlDateTimeFormatConstructor: Create obj failed.");
125 return nullptr;
126 }
127 status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj), IntlDateTimeFormatAddon::Destructor,
128 nullptr, nullptr);
129 if (status != napi_ok) {
130 delete obj;
131 HILOG_ERROR_I18N(
132 "IntlDateTimeFormatAddon::IntlDateTimeFormatConstructor: Wrap IntlDateTimeFormatAddon failed");
133 return nullptr;
134 }
135 if (!obj->InitIntlDateTimeFormatContext(env, localeTags, configs)) {
136 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::IntlDateTimeFormatConstructor: Init IntlDateTimeFormat failed");
137 return nullptr;
138 }
139 return thisVar;
140 }
141
CreateDateTimeFormatWithoutNew(napi_env env,size_t argc,napi_value * argv)142 napi_value IntlDateTimeFormatAddon::CreateDateTimeFormatWithoutNew(napi_env env, size_t argc, napi_value *argv)
143 {
144 napi_value exception;
145 napi_status status = napi_get_and_clear_last_exception(env, &exception);
146 if (status != napi_ok) {
147 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateDateTimeFormatWithoutNew: Clear last exception failed");
148 return nullptr;
149 }
150
151 napi_value constructor = nullptr;
152 status = napi_get_reference_value(env, *g_IntlDateTimeFormatConstructor, &constructor);
153 if (status != napi_ok || constructor == nullptr) {
154 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateDateTimeFormatWithoutNew: napi_get_reference_value failed");
155 return nullptr;
156 }
157
158 napi_value instance = nullptr;
159 status = napi_new_instance(env, constructor, argc, argv, &instance);
160 if (status != napi_ok) {
161 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateDateTimeFormatWithoutNew: napi_new_instance failed");
162 return nullptr;
163 }
164 return instance;
165 }
166
ParseConfigs(napi_env env,napi_value options,std::unordered_map<std::string,std::string> & configs)167 void IntlDateTimeFormatAddon::ParseConfigs(napi_env env, napi_value options,
168 std::unordered_map<std::string, std::string>& configs)
169 {
170 napi_valuetype type = napi_undefined;
171 napi_status status = napi_typeof(env, options, &type);
172 if (status != napi_ok) {
173 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::ParseConfigs: Get options type failed.");
174 return;
175 }
176 if (type != napi_object) {
177 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::ParseConfigs: options is not object.");
178 return;
179 }
180 std::string value;
181 std::unordered_set<std::string> keyOfTypeString = { IntlDateTimeFormat::LOCALE_MATCHER_TAG,
182 IntlDateTimeFormat::WEEK_DAY_TAG, IntlDateTimeFormat::ERA_TAG, IntlDateTimeFormat::YEAR_TAG,
183 IntlDateTimeFormat::MONTH_TAG, IntlDateTimeFormat::DAY_TAG, IntlDateTimeFormat::HOUR_TAG,
184 IntlDateTimeFormat::MINUTE_TAG, IntlDateTimeFormat::SECOND_TAG, IntlDateTimeFormat::TIME_ZONE_NAME_TAG,
185 IntlDateTimeFormat::FORMAT_MATCHER_TAG, IntlDateTimeFormat::TIME_ZONE_TAG, IntlDateTimeFormat::DATE_STYLE_TAG,
186 IntlDateTimeFormat::TIME_STYLE_TAG, IntlDateTimeFormat::HOUR_CYCLE_TAG, IntlDateTimeFormat::DAY_PERIOD_TAG,
187 IntlDateTimeFormat::CALENDAR_TAG, IntlDateTimeFormat::NUMBERING_SYSTEM_TAG
188 };
189 for (const auto& key : keyOfTypeString) {
190 if (JSUtils::GetPropertyFormObject(env, options, key, napi_string, value)) {
191 configs.insert(std::make_pair(key, value));
192 }
193 }
194 if (JSUtils::GetPropertyFormObject(env, options, IntlDateTimeFormat::HOUR12_TAG, napi_boolean, value)) {
195 configs.insert({IntlDateTimeFormat::HOUR12_TAG, value});
196 }
197 if (JSUtils::GetPropertyFormObject(env, options, IntlDateTimeFormat::FRACTIONAL_SECOND_DIGITS_TAG, napi_number,
198 value)) {
199 configs.insert({IntlDateTimeFormat::FRACTIONAL_SECOND_DIGITS_TAG, value});
200 }
201 }
202
InitIntlDateTimeFormatContext(napi_env env,const std::vector<std::string> & localeTags,std::unordered_map<std::string,std::string> & configs)203 bool IntlDateTimeFormatAddon::InitIntlDateTimeFormatContext(napi_env env, const std::vector<std::string>& localeTags,
204 std::unordered_map<std::string, std::string>& configs)
205 {
206 std::string errMessage;
207 intlDateTimeFormat = std::make_unique<IntlDateTimeFormat>(localeTags, configs, errMessage);
208 if (!errMessage.empty()) {
209 ErrorUtil::NapiThrowUndefined(env, errMessage);
210 return false;
211 }
212 return intlDateTimeFormat != nullptr;
213 }
214
Format(napi_env env,napi_callback_info info)215 napi_value IntlDateTimeFormatAddon::Format(napi_env env, napi_callback_info info)
216 {
217 size_t argc = 1;
218 napi_value argv[1] = { nullptr };
219 napi_value thisVar = nullptr;
220 void *data = nullptr;
221 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
222 if (status != napi_ok) {
223 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::Format: get cb info failed.");
224 return JSUtils::CreateEmptyString(env);
225 }
226 double milliseconds = 0;
227 if (argc < 1 || !GetDateTime(env, argv[0], milliseconds)) {
228 std::chrono::milliseconds ms = std::chrono::duration_cast< std::chrono::milliseconds >(
229 std::chrono::system_clock::now().time_since_epoch()
230 );
231 milliseconds = ms.count();
232 }
233
234 IntlDateTimeFormatAddon* obj = nullptr;
235 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
236 if (status != napi_ok || !obj || !obj->intlDateTimeFormat) {
237 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::Format: unwrap IntlDateTimeFormatAddon failed.");
238 return JSUtils::CreateEmptyString(env);
239 }
240 std::string formatResult = obj->intlDateTimeFormat->Format(milliseconds);
241 napi_value result = nullptr;
242 status = napi_create_string_utf8(env, formatResult.c_str(), NAPI_AUTO_LENGTH, &result);
243 if (status != napi_ok) {
244 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::::Format: Create string failed.");
245 return JSUtils::CreateEmptyString(env);
246 }
247 return result;
248 }
249
FormatToParts(napi_env env,napi_callback_info info)250 napi_value IntlDateTimeFormatAddon::FormatToParts(napi_env env, napi_callback_info info)
251 {
252 size_t argc = 1;
253 napi_value argv[1] = { nullptr };
254 napi_value thisVar = nullptr;
255 void *data = nullptr;
256 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
257 if (status != napi_ok) {
258 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::FormatToParts: get cb info failed.");
259 return JSUtils::CreateEmptyArray(env);
260 }
261 double milliseconds = 0;
262 if (argc < 1 || !GetDateTime(env, argv[0], milliseconds)) {
263 std::chrono::milliseconds ms = std::chrono::duration_cast< std::chrono::milliseconds >(
264 std::chrono::system_clock::now().time_since_epoch()
265 );
266 milliseconds = ms.count();
267 }
268
269 IntlDateTimeFormatAddon* obj = nullptr;
270 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
271 if (status != napi_ok || !obj || !obj->intlDateTimeFormat) {
272 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::FormatToParts: unwrap IntlDateTimeFormatAddon failed.");
273 return JSUtils::CreateEmptyArray(env);
274 }
275 std::string errMessage;
276 std::vector<std::pair<std::string, std::string>> formatResult =
277 obj->intlDateTimeFormat->FormatToParts(milliseconds, errMessage);
278 if (!errMessage.empty()) {
279 ErrorUtil::NapiThrowUndefined(env, errMessage);
280 return nullptr;
281 }
282 return CreateFormatPart(env, formatResult);
283 }
284
FormatRange(napi_env env,napi_callback_info info)285 napi_value IntlDateTimeFormatAddon::FormatRange(napi_env env, napi_callback_info info)
286 {
287 size_t argc = NUMBER_OF_PARAMETER;
288 napi_value argv[NUMBER_OF_PARAMETER] = { nullptr };
289 napi_value thisVar = nullptr;
290 void *data = nullptr;
291 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
292 if (status != napi_ok) {
293 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::FormatRange: get cb info failed.");
294 return JSUtils::CreateEmptyString(env);
295 } else if (argc < NUMBER_OF_PARAMETER) {
296 ErrorUtil::NapiThrowUndefined(env, "startDate or endDate is undefined");
297 return nullptr;
298 }
299
300 double start = 0;
301 if (!GetDateTime(env, argv[0], start)) {
302 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::FormatRange: get date time from argv[0] failed.");
303 return JSUtils::CreateEmptyString(env);
304 }
305 double end = 0;
306 if (!GetDateTime(env, argv[1], end)) {
307 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::FormatRange: get date time from argv[1] failed.");
308 return JSUtils::CreateEmptyString(env);
309 }
310
311 IntlDateTimeFormatAddon* obj = nullptr;
312 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
313 if (status != napi_ok || !obj || !obj->intlDateTimeFormat) {
314 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::FormatRange: unwrap IntlDateTimeFormatAddon failed.");
315 return JSUtils::CreateEmptyString(env);
316 }
317 std::string errMessage;
318 std::string formatResult = obj->intlDateTimeFormat->FormatRange(start, end, errMessage);
319 if (!errMessage.empty()) {
320 ErrorUtil::NapiThrowUndefined(env, errMessage);
321 return nullptr;
322 }
323 napi_value result = nullptr;
324 status = napi_create_string_utf8(env, formatResult.c_str(), NAPI_AUTO_LENGTH, &result);
325 if (status != napi_ok) {
326 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::FormatRange: Create string failed.");
327 return JSUtils::CreateEmptyString(env);
328 }
329 return result;
330 }
331
FormatRangeToParts(napi_env env,napi_callback_info info)332 napi_value IntlDateTimeFormatAddon::FormatRangeToParts(napi_env env, napi_callback_info info)
333 {
334 size_t argc = NUMBER_OF_PARAMETER;
335 napi_value argv[NUMBER_OF_PARAMETER] = { nullptr };
336 napi_value thisVar = nullptr;
337 void *data = nullptr;
338 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
339 if (status != napi_ok) {
340 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::FormatRangeToParts: get cb info failed.");
341 return JSUtils::CreateEmptyArray(env);
342 } else if (argc < NUMBER_OF_PARAMETER) {
343 ErrorUtil::NapiThrowUndefined(env, "startDate or endDate is undefined");
344 return nullptr;
345 }
346
347 double start = 0;
348 if (!GetDateTime(env, argv[0], start)) {
349 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::FormatRangeToParts: get date time from argv[0] failed.");
350 return JSUtils::CreateEmptyArray(env);
351 }
352 double end = 0;
353 if (!GetDateTime(env, argv[1], end)) {
354 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::FormatRangeToParts: get date time from argv[1] failed.");
355 return JSUtils::CreateEmptyArray(env);
356 }
357
358 IntlDateTimeFormatAddon* obj = nullptr;
359 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
360 if (status != napi_ok || !obj || !obj->intlDateTimeFormat) {
361 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::FormatRangeToParts: unwrap IntlDateTimeFormatAddon failed.");
362 return JSUtils::CreateEmptyArray(env);
363 }
364 std::string errMessage;
365 std::vector<std::pair<std::string, std::string>> formatResult =
366 obj->intlDateTimeFormat->FormatRangeToParts(start, end, errMessage);
367 if (!errMessage.empty()) {
368 ErrorUtil::NapiThrowUndefined(env, errMessage);
369 return nullptr;
370 }
371 return CreateFormatPart(env, formatResult);
372 }
373
ResolvedOptions(napi_env env,napi_callback_info info)374 napi_value IntlDateTimeFormatAddon::ResolvedOptions(napi_env env, napi_callback_info info)
375 {
376 size_t argc = NUMBER_OF_PARAMETER;
377 napi_value argv[NUMBER_OF_PARAMETER] = { nullptr };
378 napi_value thisVar = nullptr;
379 void *data = nullptr;
380 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
381 if (status != napi_ok) {
382 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::ResolvedOptions: get cb info failed.");
383 return JSUtils::CreateEmptyObject(env);
384 }
385 IntlDateTimeFormatAddon* obj = nullptr;
386 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
387 if (status != napi_ok || !obj || !obj->intlDateTimeFormat) {
388 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::ResolvedOptions: unwrap IntlDateTimeFormatAddon failed.");
389 return JSUtils::CreateEmptyObject(env);
390 }
391 std::unordered_map<std::string, std::string> configs;
392 obj->intlDateTimeFormat->ResolvedOptions(configs);
393 return CreateResolvedOptions(env, configs);
394 }
395
SupportedLocalesOf(napi_env env,napi_callback_info info)396 napi_value IntlDateTimeFormatAddon::SupportedLocalesOf(napi_env env, napi_callback_info info)
397 {
398 size_t argc = NUMBER_OF_PARAMETER;
399 napi_value argv[NUMBER_OF_PARAMETER] = { nullptr };
400 napi_value thisVar = nullptr;
401 void *data = nullptr;
402 std::vector<std::string> resultLocales = {};
403 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
404 if (status != napi_ok) {
405 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::SupportedLocalesOf: napi get callback info failed.");
406 return JSUtils::CreateArray(env, resultLocales);
407 }
408 std::vector<std::string> localeTags;
409 if (argc > 0) {
410 int32_t code = 0;
411 std::vector<std::string> localeArray = JSUtils::GetLocaleArray(env, argv[0], code);
412 localeTags.assign(localeArray.begin(), localeArray.end());
413 }
414 std::map<std::string, std::string> map = {};
415 if (argc > 1) {
416 JSUtils::GetOptionValue(env, argv[1], "localeMatcher", map);
417 }
418 I18nErrorCode i18nStatus = I18nErrorCode::SUCCESS;
419 resultLocales = IntlDateTimeFormat::SupportedLocalesOf(localeTags, map, i18nStatus);
420 if (i18nStatus == I18nErrorCode::INVALID_PARAM) {
421 ErrorUtil::NapiThrowUndefined(env, "getStringOption failed");
422 return nullptr;
423 } else if (i18nStatus == I18nErrorCode::INVALID_LOCALE_TAG) {
424 ErrorUtil::NapiThrowUndefined(env, "invalid locale");
425 return nullptr;
426 }
427 return JSUtils::CreateArray(env, resultLocales);
428 }
429
GetDateTime(napi_env env,napi_value time,double & milliseconds)430 bool IntlDateTimeFormatAddon::GetDateTime(napi_env env, napi_value time, double& milliseconds)
431 {
432 bool isDate = false;
433 napi_status status = napi_is_date(env, time, &isDate);
434 if (status != napi_ok) {
435 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::GetDateTime: Call napi_is_date failed.");
436 return false;
437 }
438 if (isDate) {
439 status = napi_get_date_value(env, time, &milliseconds);
440 if (status != napi_ok) {
441 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::GetDateTime: Get date value failed.");
442 return false;
443 }
444 return true;
445 }
446
447 napi_valuetype type = napi_undefined;
448 status = napi_typeof(env, time, &type);
449 if (status != napi_ok) {
450 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::GetDateTime: Get time type failed.");
451 return false;
452 }
453 if (type != napi_valuetype::napi_number) {
454 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::GetDateTime: Check type failed.");
455 return false;
456 }
457 status = napi_get_value_double(env, time, &milliseconds);
458 if (status != napi_ok) {
459 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::GetDateTime: Get get value double failed.");
460 return false;
461 }
462 return true;
463 }
464
CreateFormatPart(napi_env env,const std::vector<std::pair<std::string,std::string>> & formatResult)465 napi_value IntlDateTimeFormatAddon::CreateFormatPart(napi_env env,
466 const std::vector<std::pair<std::string, std::string>>& formatResult)
467 {
468 size_t length = formatResult.size();
469 napi_value result = nullptr;
470 napi_status status = napi_create_array_with_length(env, length, &result);
471 if (status != napi_ok || result == nullptr) {
472 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateFormatPart: Create array failed.");
473 return JSUtils::CreateEmptyArray(env);
474 }
475 size_t index = 0;
476 for (const auto& item : formatResult) {
477 napi_value object = nullptr;
478 status = napi_create_object(env, &object);
479 if (status != napi_ok || object == nullptr) {
480 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateFormatPart: Create object failed.");
481 return JSUtils::CreateEmptyArray(env);
482 }
483 napi_value type = nullptr;
484 status = napi_create_string_utf8(env, item.first.c_str(), NAPI_AUTO_LENGTH, &type);
485 if (status != napi_ok || type == nullptr) {
486 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateFormatPart: Create type failed.");
487 return JSUtils::CreateEmptyArray(env);
488 }
489 status = napi_set_named_property(env, object, "type", type);
490 if (status != napi_ok) {
491 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateFormatPart: Set property type failed.");
492 return JSUtils::CreateEmptyArray(env);
493 }
494 napi_value value = nullptr;
495 status = napi_create_string_utf8(env, item.second.c_str(), NAPI_AUTO_LENGTH, &value);
496 if (status != napi_ok || value == nullptr) {
497 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateFormatPart: Create type failed.");
498 return JSUtils::CreateEmptyArray(env);
499 }
500 status = napi_set_named_property(env, object, "value", value);
501 if (status != napi_ok) {
502 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateFormatPart: Set property type failed.");
503 return JSUtils::CreateEmptyArray(env);
504 }
505 status = napi_set_element(env, result, index, object);
506 if (status != napi_ok) {
507 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateFormatPart: Set element failed, index is %{public}zu.",
508 index);
509 return JSUtils::CreateEmptyArray(env);
510 }
511 index++;
512 }
513 return result;
514 }
515
CreateResolvedOptions(napi_env env,const std::unordered_map<std::string,std::string> & configs)516 napi_value IntlDateTimeFormatAddon::CreateResolvedOptions(napi_env env,
517 const std::unordered_map<std::string, std::string>& configs)
518 {
519 napi_value object = nullptr;
520 napi_status status = napi_create_object(env, &object);
521 if (status != napi_ok || object == nullptr) {
522 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateFormatPart: Create object failed.");
523 return JSUtils::CreateEmptyObject(env);
524 }
525
526 for (auto& config : configs) {
527 std::string key = config.first;
528 std::string value = config.second;
529 napi_value propertyValue = nullptr;
530 if (key.compare(IntlDateTimeFormat::HOUR12_TAG) == 0) {
531 bool boolValue = (value.compare("true") == 0) ? true : false;
532 status = napi_get_boolean(env, boolValue, &propertyValue);
533 } else if (key.compare(IntlDateTimeFormat::FRACTIONAL_SECOND_DIGITS_TAG) == 0) {
534 int32_t code = 0;
535 int32_t intValue = ConvertString2Int(value, code);
536 if (code != 0) {
537 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateResolvedOptions: Convert string failed.");
538 continue;
539 }
540 status = napi_create_int32(env, intValue, &propertyValue);
541 } else {
542 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &propertyValue);
543 }
544 if (status != napi_ok || propertyValue == nullptr) {
545 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateResolvedOptions: Create propertyValue failed.");
546 continue;
547 }
548 status = napi_set_named_property(env, object, key.c_str(), propertyValue);
549 if (status != napi_ok) {
550 HILOG_ERROR_I18N("IntlDateTimeFormatAddon::CreateResolvedOptions: Set property failed.");
551 }
552 }
553 return object;
554 }
555 } // namespace I18n
556 } // namespace Global
557 } // namespace OHOS