1 /*
2 * Copyright (c) 2023 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 <unordered_map>
17 #include <unordered_set>
18
19 #include "error_util.h"
20 #include "i18n_hilog.h"
21 #include "i18n_calendar_addon.h"
22 #include "js_utils.h"
23 #include "variable_convertor.h"
24
25 namespace OHOS {
26 namespace Global {
27 namespace I18n {
28 static thread_local napi_ref* g_constructor = nullptr;
29 static std::unordered_map<std::string, UCalendarDateFields> g_fieldsMap {
30 { "era", UCAL_ERA },
31 { "year", UCAL_YEAR },
32 { "month", UCAL_MONTH },
33 { "week_of_year", UCAL_WEEK_OF_YEAR },
34 { "week_of_month", UCAL_WEEK_OF_MONTH },
35 { "date", UCAL_DATE },
36 { "day_of_year", UCAL_DAY_OF_YEAR },
37 { "day_of_week", UCAL_DAY_OF_WEEK },
38 { "day_of_week_in_month", UCAL_DAY_OF_WEEK_IN_MONTH },
39 { "ap_pm", UCAL_AM_PM },
40 { "hour", UCAL_HOUR },
41 { "hour_of_day", UCAL_HOUR_OF_DAY },
42 { "minute", UCAL_MINUTE },
43 { "second", UCAL_SECOND },
44 { "millisecond", UCAL_MILLISECOND },
45 { "zone_offset", UCAL_ZONE_OFFSET },
46 { "dst_offset", UCAL_DST_OFFSET },
47 { "year_woy", UCAL_YEAR_WOY },
48 { "dow_local", UCAL_DOW_LOCAL },
49 { "extended_year", UCAL_EXTENDED_YEAR },
50 { "julian_day", UCAL_JULIAN_DAY },
51 { "milliseconds_in_day", UCAL_MILLISECONDS_IN_DAY },
52 { "is_leap_month", UCAL_IS_LEAP_MONTH },
53 };
54 static std::unordered_set<std::string> g_fieldsInFunctionAdd {
55 "year", "month", "date", "hour", "minute", "second", "millisecond",
56 "week_of_year", "week_of_month", "day_of_year", "day_of_week",
57 "day_of_week_in_month", "hour_of_day", "milliseconds_in_day",
58 };
59 static std::unordered_map<std::string, CalendarType> g_typeMap {
60 { "buddhist", CalendarType::BUDDHIST },
61 { "chinese", CalendarType::CHINESE },
62 { "coptic", CalendarType::COPTIC },
63 { "ethiopic", CalendarType::ETHIOPIC },
64 { "hebrew", CalendarType::HEBREW },
65 { "gregory", CalendarType::GREGORY },
66 { "indian", CalendarType::INDIAN },
67 { "islamic_civil", CalendarType::ISLAMIC_CIVIL },
68 { "islamic_tbla", CalendarType::ISLAMIC_TBLA },
69 { "islamic_umalqura", CalendarType::ISLAMIC_UMALQURA },
70 { "japanese", CalendarType::JAPANESE },
71 { "persian", CalendarType::PERSIAN },
72 };
73
I18nCalendarAddon()74 I18nCalendarAddon::I18nCalendarAddon() {}
75
~I18nCalendarAddon()76 I18nCalendarAddon::~I18nCalendarAddon() {}
77
Destructor(napi_env env,void * nativeObject,void * hint)78 void I18nCalendarAddon::Destructor(napi_env env, void *nativeObject, void *hint)
79 {
80 if (!nativeObject) {
81 return;
82 }
83 delete reinterpret_cast<I18nCalendarAddon *>(nativeObject);
84 nativeObject = nullptr;
85 }
86
InitI18nCalendar(napi_env env,napi_value exports)87 napi_value I18nCalendarAddon::InitI18nCalendar(napi_env env, napi_value exports)
88 {
89 napi_property_descriptor properties[] = {
90 DECLARE_NAPI_FUNCTION("setTime", SetTime),
91 DECLARE_NAPI_FUNCTION("set", Set),
92 DECLARE_NAPI_FUNCTION("getTimeZone", GetTimeZone),
93 DECLARE_NAPI_FUNCTION("setTimeZone", SetTimeZone),
94 DECLARE_NAPI_FUNCTION("getFirstDayOfWeek", GetFirstDayOfWeek),
95 DECLARE_NAPI_FUNCTION("setFirstDayOfWeek", SetFirstDayOfWeek),
96 DECLARE_NAPI_FUNCTION("getMinimalDaysInFirstWeek", GetMinimalDaysInFirstWeek),
97 DECLARE_NAPI_FUNCTION("setMinimalDaysInFirstWeek", SetMinimalDaysInFirstWeek),
98 DECLARE_NAPI_FUNCTION("get", Get),
99 DECLARE_NAPI_FUNCTION("add", Add),
100 DECLARE_NAPI_FUNCTION("getDisplayName", GetDisplayName),
101 DECLARE_NAPI_FUNCTION("getTimeInMillis", GetTimeInMillis),
102 DECLARE_NAPI_FUNCTION("isWeekend", IsWeekend),
103 DECLARE_NAPI_FUNCTION("compareDays", CompareDays)
104 };
105 napi_value constructor = nullptr;
106 napi_status status = napi_define_class(env, "Calendar", NAPI_AUTO_LENGTH, I18nCalendarConstructor, nullptr,
107 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
108 if (status != napi_ok) {
109 HILOG_ERROR_I18N("Failed to define class at Init");
110 return nullptr;
111 }
112 exports = I18nCalendarAddon::InitCalendar(env, exports);
113 g_constructor = new (std::nothrow) napi_ref;
114 if (!g_constructor) {
115 HILOG_ERROR_I18N("Failed to create ref at init");
116 return nullptr;
117 }
118 status = napi_create_reference(env, constructor, 1, g_constructor);
119 if (status != napi_ok) {
120 HILOG_ERROR_I18N("Failed to create reference at init");
121 return nullptr;
122 }
123 return exports;
124 }
125
InitCalendar(napi_env env,napi_value exports)126 napi_value I18nCalendarAddon::InitCalendar(napi_env env, napi_value exports)
127 {
128 napi_property_descriptor properties[] = {};
129 napi_value constructor = nullptr;
130 napi_status status = napi_define_class(env, "I18nCalendar", NAPI_AUTO_LENGTH, JSUtils::DefaultConstructor, nullptr,
131 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
132 if (status != napi_ok) {
133 HILOG_ERROR_I18N("InitCalendar: Failed to define class Calendar.");
134 return nullptr;
135 }
136 status = napi_set_named_property(env, exports, "Calendar", constructor);
137 if (status != napi_ok) {
138 HILOG_ERROR_I18N("InitCalendar: Set property failed When InitCalendar.");
139 return nullptr;
140 }
141 return exports;
142 }
143
GetCalendar(napi_env env,napi_callback_info info)144 napi_value I18nCalendarAddon::GetCalendar(napi_env env, napi_callback_info info)
145 {
146 size_t argc = 2; // retrieve 2 arguments
147 napi_value argv[2] = { 0 };
148 argv[0] = nullptr;
149 argv[1] = nullptr;
150 napi_value thisVar = nullptr;
151 void *data = nullptr;
152 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
153 if (status != napi_ok) {
154 return nullptr;
155 }
156 napi_value constructor = nullptr;
157 if (g_constructor == nullptr) {
158 HILOG_ERROR_I18N("Failed to create g_constructor");
159 return nullptr;
160 }
161 status = napi_get_reference_value(env, *g_constructor, &constructor);
162 if (status != napi_ok) {
163 HILOG_ERROR_I18N("Failed to create reference at GetCalendar");
164 return nullptr;
165 }
166 napi_valuetype valueType = napi_valuetype::napi_undefined;
167 status = napi_typeof(env, argv[1], &valueType);
168 if (status != napi_ok) {
169 return nullptr;
170 }
171 if (valueType != napi_valuetype::napi_string) {
172 status = napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, argv + 1);
173 if (status != napi_ok) {
174 return nullptr;
175 }
176 }
177 napi_value result = nullptr;
178 status = napi_new_instance(env, constructor, 2, argv, &result); // 2 arguments
179 if (status != napi_ok) {
180 HILOG_ERROR_I18N("Get calendar create instance failed");
181 return nullptr;
182 }
183 return result;
184 }
185
I18nCalendarConstructor(napi_env env,napi_callback_info info)186 napi_value I18nCalendarAddon::I18nCalendarConstructor(napi_env env, napi_callback_info info)
187 {
188 size_t argc = 2;
189 napi_value argv[2] = { 0 };
190 argv[0] = nullptr;
191 argv[1] = nullptr;
192 napi_value thisVar = nullptr;
193 void *data = nullptr;
194 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
195 if (status != napi_ok) {
196 return nullptr;
197 }
198 napi_valuetype valueType = napi_valuetype::napi_undefined;
199 status = napi_typeof(env, argv[0], &valueType);
200 if (status != napi_ok) {
201 return nullptr;
202 }
203 if (valueType != napi_valuetype::napi_string) {
204 HILOG_ERROR_I18N("CalendarConstructor: Parameter type does not match");
205 return nullptr;
206 }
207 int32_t code = 0;
208 std::string localeTag = VariableConvertor::GetString(env, argv[0], code);
209 if (code) {
210 return nullptr;
211 }
212 CalendarType type = GetCalendarType(env, argv[1]);
213 std::unique_ptr<I18nCalendarAddon> obj = nullptr;
214 obj = std::make_unique<I18nCalendarAddon>();
215 if (obj == nullptr) {
216 return nullptr;
217 }
218 status =
219 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nCalendarAddon::Destructor, nullptr, nullptr);
220 if (status != napi_ok) {
221 HILOG_ERROR_I18N("CalendarConstructor: Wrap II18nAddon failed");
222 return nullptr;
223 }
224 if (!obj->InitCalendarContext(env, info, localeTag, type)) {
225 return nullptr;
226 }
227 obj.release();
228 return thisVar;
229 }
230
SetTime(napi_env env,napi_callback_info info)231 napi_value I18nCalendarAddon::SetTime(napi_env env, napi_callback_info info)
232 {
233 size_t argc = 1;
234 napi_value argv[1] = { 0 };
235 argv[0] = nullptr;
236 napi_value thisVar = nullptr;
237 void *data = nullptr;
238 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
239 if (status != napi_ok) {
240 return nullptr;
241 }
242 if (!argv[0]) {
243 return nullptr;
244 }
245 I18nCalendarAddon *obj = nullptr;
246 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
247 if (status != napi_ok || !obj || !obj->calendar_) {
248 HILOG_ERROR_I18N("SetTime: Get calendar object failed");
249 return nullptr;
250 }
251 napi_valuetype type = napi_valuetype::napi_undefined;
252 status = napi_typeof(env, argv[0], &type);
253 if (status != napi_ok) {
254 return nullptr;
255 }
256 if (type == napi_valuetype::napi_number) {
257 obj->SetMilliseconds(env, argv[0]);
258 return nullptr;
259 } else {
260 napi_value val = GetDate(env, argv[0]);
261 if (!val) {
262 return nullptr;
263 }
264 obj->SetMilliseconds(env, val);
265 return nullptr;
266 }
267 }
268
Set(napi_env env,napi_callback_info info)269 napi_value I18nCalendarAddon::Set(napi_env env, napi_callback_info info)
270 {
271 size_t argc = 6; // Set may have 6 arguments
272 napi_value argv[6] = { 0 };
273 for (size_t i = 0; i < argc; ++i) {
274 argv[i] = nullptr;
275 }
276 napi_value thisVar = nullptr;
277 void *data = nullptr;
278 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
279 if (status != napi_ok) {
280 return nullptr;
281 }
282 napi_valuetype valueType = napi_valuetype::napi_undefined;
283 int32_t times[3] = { 0 }; // There are at least 3 arguments.
284 for (int i = 0; i < 3; ++i) { // There are at least 3 arguments.
285 status = napi_typeof(env, argv[i], &valueType);
286 if (status != napi_ok) {
287 return nullptr;
288 }
289 if (valueType != napi_valuetype::napi_number) {
290 HILOG_ERROR_I18N("Set: Parameter type does not match");
291 return nullptr;
292 }
293 status = napi_get_value_int32(env, argv[i], times + i);
294 if (status != napi_ok) {
295 HILOG_ERROR_I18N("Set: Retrieve time value failed");
296 return nullptr;
297 }
298 }
299 I18nCalendarAddon *obj = nullptr;
300 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
301 if (status != napi_ok || !obj || !obj->calendar_) {
302 HILOG_ERROR_I18N("Set: Get calendar object failed");
303 return nullptr;
304 }
305 obj->calendar_->Set(times[0], times[1], times[2]); // 2 is the index of date
306 obj->SetField(env, argv[3], UCalendarDateFields::UCAL_HOUR_OF_DAY); // 3 is the index of hour
307 obj->SetField(env, argv[4], UCalendarDateFields::UCAL_MINUTE); // 4 is the index of minute
308 obj->SetField(env, argv[5], UCalendarDateFields::UCAL_SECOND); // 5 is the index of second
309 return nullptr;
310 }
311
GetTimeZone(napi_env env,napi_callback_info info)312 napi_value I18nCalendarAddon::GetTimeZone(napi_env env, napi_callback_info info)
313 {
314 size_t argc = 0;
315 napi_value *argv = nullptr;
316 napi_value thisVar = nullptr;
317 void *data = nullptr;
318 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
319 if (status != napi_ok) {
320 return nullptr;
321 }
322 I18nCalendarAddon *obj = nullptr;
323 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
324 if (status != napi_ok || !obj || !obj->calendar_) {
325 HILOG_ERROR_I18N("GetTimeZone: Get calendar object failed");
326 return nullptr;
327 }
328 std::string temp = obj->calendar_->GetTimeZone();
329 napi_value result = nullptr;
330 status = napi_create_string_utf8(env, temp.c_str(), NAPI_AUTO_LENGTH, &result);
331 if (status != napi_ok) {
332 HILOG_ERROR_I18N("Create timezone string failed");
333 return nullptr;
334 }
335 return result;
336 }
337
SetTimeZone(napi_env env,napi_callback_info info)338 napi_value I18nCalendarAddon::SetTimeZone(napi_env env, napi_callback_info info)
339 {
340 size_t argc = 1;
341 napi_value argv[1] = { 0 };
342 argv[0] = nullptr;
343 napi_value thisVar = nullptr;
344 void *data = nullptr;
345 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
346 if (status != napi_ok) {
347 return nullptr;
348 }
349 napi_valuetype valueType = napi_valuetype::napi_undefined;
350 status = napi_typeof(env, argv[0], &valueType);
351 if (status != napi_ok) {
352 return nullptr;
353 }
354 if (valueType != napi_valuetype::napi_string) {
355 HILOG_ERROR_I18N("SetTimeZone: Parameter type does not match");
356 return nullptr;
357 }
358 size_t len = 0;
359 status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
360 if (status != napi_ok) {
361 HILOG_ERROR_I18N("SetTimeZone: Get timezone length failed");
362 return nullptr;
363 }
364 std::vector<char> buf(len + 1);
365 status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
366 if (status != napi_ok) {
367 HILOG_ERROR_I18N("SetTimeZone: Get timezone failed");
368 return nullptr;
369 }
370 std::string timezone(buf.data());
371 I18nCalendarAddon *obj = nullptr;
372 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
373 if (status != napi_ok || !obj || !obj->calendar_) {
374 HILOG_ERROR_I18N("SetTimeZone: Get calendar object failed");
375 return nullptr;
376 }
377 obj->calendar_->SetTimeZone(timezone);
378 return nullptr;
379 }
380
GetFirstDayOfWeek(napi_env env,napi_callback_info info)381 napi_value I18nCalendarAddon::GetFirstDayOfWeek(napi_env env, napi_callback_info info)
382 {
383 size_t argc = 0;
384 napi_value *argv = nullptr;
385 napi_value thisVar = nullptr;
386 void *data = nullptr;
387 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
388 if (status != napi_ok) {
389 return nullptr;
390 }
391 I18nCalendarAddon *obj = nullptr;
392 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
393 if (status != napi_ok || !obj || !obj->calendar_) {
394 HILOG_ERROR_I18N("GetFirstDayOfWeek: Get calendar object failed");
395 return nullptr;
396 }
397 int32_t temp = obj->calendar_->GetFirstDayOfWeek();
398 napi_value result = nullptr;
399 status = napi_create_int32(env, temp, &result);
400 if (status != napi_ok) {
401 HILOG_ERROR_I18N("GetFirstDayOfWeek: Create int32 failed");
402 return nullptr;
403 }
404 return result;
405 }
406
SetFirstDayOfWeek(napi_env env,napi_callback_info info)407 napi_value I18nCalendarAddon::SetFirstDayOfWeek(napi_env env, napi_callback_info info)
408 {
409 size_t argc = 1;
410 napi_value argv[1] = { 0 };
411 argv[0] = nullptr;
412 napi_value thisVar = nullptr;
413 void *data = nullptr;
414 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
415 if (status != napi_ok) {
416 return nullptr;
417 }
418 napi_valuetype valueType = napi_valuetype::napi_undefined;
419 status = napi_typeof(env, argv[0], &valueType);
420 if (status != napi_ok) {
421 return nullptr;
422 }
423 if (valueType != napi_valuetype::napi_number) {
424 HILOG_ERROR_I18N("SetFirstDayOfWeek: Parameter type does not match");
425 return nullptr;
426 }
427 int32_t value = 0;
428 status = napi_get_value_int32(env, argv[0], &value);
429 if (status != napi_ok) {
430 HILOG_ERROR_I18N("SetFirstDayOfWeek: Get int32 failed");
431 return nullptr;
432 }
433 I18nCalendarAddon *obj = nullptr;
434 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
435 if (status != napi_ok || !obj || !obj->calendar_) {
436 HILOG_ERROR_I18N("SetFirstDayOfWeek: Get calendar object failed");
437 return nullptr;
438 }
439 obj->calendar_->SetFirstDayOfWeek(value);
440 return nullptr;
441 }
442
GetMinimalDaysInFirstWeek(napi_env env,napi_callback_info info)443 napi_value I18nCalendarAddon::GetMinimalDaysInFirstWeek(napi_env env, napi_callback_info info)
444 {
445 size_t argc = 0;
446 napi_value *argv = nullptr;
447 napi_value thisVar = nullptr;
448 void *data = nullptr;
449 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
450 if (status != napi_ok) {
451 return nullptr;
452 }
453 I18nCalendarAddon *obj = nullptr;
454 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
455 if (status != napi_ok || !obj || !obj->calendar_) {
456 HILOG_ERROR_I18N("GetMinimalDaysInFirstWeek: Get calendar object failed");
457 return nullptr;
458 }
459 int32_t temp = obj->calendar_->GetMinimalDaysInFirstWeek();
460 napi_value result = nullptr;
461 status = napi_create_int32(env, temp, &result);
462 if (status != napi_ok) {
463 HILOG_ERROR_I18N("GetMinimalDaysInFirstWeek: Create int32 failed");
464 return nullptr;
465 }
466 return result;
467 }
468
SetMinimalDaysInFirstWeek(napi_env env,napi_callback_info info)469 napi_value I18nCalendarAddon::SetMinimalDaysInFirstWeek(napi_env env, napi_callback_info info)
470 {
471 size_t argc = 1;
472 napi_value argv[1] = { 0 };
473 argv[0] = nullptr;
474 napi_value thisVar = nullptr;
475 void *data = nullptr;
476 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
477 if (status != napi_ok) {
478 return nullptr;
479 }
480 napi_valuetype valueType = napi_valuetype::napi_undefined;
481 status = napi_typeof(env, argv[0], &valueType);
482 if (status != napi_ok) {
483 return nullptr;
484 }
485 if (valueType != napi_valuetype::napi_number) {
486 HILOG_ERROR_I18N("SetMinimalDaysInFirstWeek: Parameter type does not match");
487 return nullptr;
488 }
489 int32_t value = 0;
490 status = napi_get_value_int32(env, argv[0], &value);
491 if (status != napi_ok) {
492 HILOG_ERROR_I18N("SetMinimalDaysInFirstWeek: Get int32 failed");
493 return nullptr;
494 }
495 I18nCalendarAddon *obj = nullptr;
496 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
497 if (status != napi_ok || !obj || !obj->calendar_) {
498 HILOG_ERROR_I18N("SetMinimalDaysInFirstWeek: Get calendar object failed");
499 return nullptr;
500 }
501 obj->calendar_->SetMinimalDaysInFirstWeek(value);
502 return nullptr;
503 }
504
Get(napi_env env,napi_callback_info info)505 napi_value I18nCalendarAddon::Get(napi_env env, napi_callback_info info)
506 {
507 size_t argc = 1;
508 napi_value argv[1] = { 0 };
509 argv[0] = nullptr;
510 napi_value thisVar = nullptr;
511 void *data = nullptr;
512 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
513 if (status != napi_ok) {
514 return nullptr;
515 }
516 napi_valuetype valueType = napi_valuetype::napi_undefined;
517 status = napi_typeof(env, argv[0], &valueType);
518 if (status != napi_ok) {
519 return nullptr;
520 }
521 if (valueType != napi_valuetype::napi_string) {
522 HILOG_ERROR_I18N("Get: Parameter type does not match");
523 return nullptr;
524 }
525 int32_t code = 0;
526 std::string buf = VariableConvertor::GetString(env, argv[0], code);
527 if (code) {
528 return nullptr;
529 }
530 std::string field(buf.data());
531 if (g_fieldsMap.find(field) == g_fieldsMap.end()) {
532 HILOG_ERROR_I18N("Invalid field");
533 return nullptr;
534 }
535 I18nCalendarAddon *obj = nullptr;
536 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
537 if (status != napi_ok || !obj || !obj->calendar_) {
538 HILOG_ERROR_I18N("Get: Get calendar object failed");
539 return nullptr;
540 }
541 int32_t value = obj->calendar_->Get(g_fieldsMap[field]);
542 napi_value result = nullptr;
543 status = napi_create_int32(env, value, &result);
544 if (status != napi_ok) {
545 HILOG_ERROR_I18N("Get: Create int32 failed");
546 return nullptr;
547 }
548 return result;
549 }
550
Add(napi_env env,napi_callback_info info)551 napi_value I18nCalendarAddon::Add(napi_env env, napi_callback_info info)
552 {
553 size_t argc = 2;
554 napi_value argv[2] = { 0 };
555 napi_value thisVar = nullptr;
556 void *data = nullptr;
557 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
558 if (status != napi_ok) {
559 HILOG_ERROR_I18N("Add: can not obtain add function param.");
560 return nullptr;
561 }
562 napi_valuetype valueType = napi_valuetype::napi_undefined;
563 status = napi_typeof(env, argv[0], &valueType);
564 if (status != napi_ok) {
565 return nullptr;
566 }
567 if (valueType != napi_valuetype::napi_string) {
568 HILOG_ERROR_I18N("Parameter type does not match argv[0]");
569 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "field", "string", true);
570 return nullptr;
571 }
572 int32_t code = 0;
573 std::string field = GetAddField(env, argv[0], code);
574 if (code) {
575 return nullptr;
576 }
577 status = napi_typeof(env, argv[1], &valueType);
578 if (status != napi_ok) {
579 return nullptr;
580 }
581 if (valueType != napi_valuetype::napi_number) {
582 HILOG_ERROR_I18N("Parameter type does not match argv[1]");
583 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "amount", "number", true);
584 return nullptr;
585 }
586 int32_t amount;
587 status = napi_get_value_int32(env, argv[1], &amount);
588 if (status != napi_ok) {
589 HILOG_ERROR_I18N("Add: Can not obtain add function param.");
590 return nullptr;
591 }
592 I18nCalendarAddon *obj = nullptr;
593 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
594 if (status != napi_ok || !obj || !obj->calendar_) {
595 HILOG_ERROR_I18N("Add: Get calendar object failed");
596 return nullptr;
597 }
598 obj->calendar_->Add(g_fieldsMap[field], amount);
599 return nullptr;
600 }
601
GetDisplayName(napi_env env,napi_callback_info info)602 napi_value I18nCalendarAddon::GetDisplayName(napi_env env, napi_callback_info info)
603 {
604 size_t argc = 1;
605 napi_value argv[1] = { 0 };
606 napi_value thisVar = nullptr;
607 void *data = nullptr;
608 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
609 if (status != napi_ok) {
610 return nullptr;
611 }
612 napi_valuetype valueType = napi_valuetype::napi_undefined;
613 status = napi_typeof(env, argv[0], &valueType);
614 if (status != napi_ok) {
615 return nullptr;
616 }
617 if (valueType != napi_valuetype::napi_string) {
618 HILOG_ERROR_I18N("GetDisplayName: Parameter type does not match");
619 return nullptr;
620 }
621 int32_t code = 0;
622 std::string localeTag = VariableConvertor::GetString(env, argv[0], code);
623 if (code) {
624 return nullptr;
625 }
626 I18nCalendarAddon *obj = nullptr;
627 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
628 if (status != napi_ok || !obj || !obj->calendar_) {
629 HILOG_ERROR_I18N("GetDisplayName: Get calendar object failed");
630 return nullptr;
631 }
632 if (!obj->calendar_) {
633 return nullptr;
634 }
635 std::string name = obj->calendar_->GetDisplayName(localeTag);
636 napi_value result = nullptr;
637 status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &result);
638 if (status != napi_ok) {
639 HILOG_ERROR_I18N("Create calendar name string failed");
640 return nullptr;
641 }
642 return result;
643 }
644
GetTimeInMillis(napi_env env,napi_callback_info info)645 napi_value I18nCalendarAddon::GetTimeInMillis(napi_env env, napi_callback_info info)
646 {
647 bool flag = true;
648 size_t argc = 0;
649 napi_value *argv = nullptr;
650 napi_value thisVar = nullptr;
651 void *data = nullptr;
652 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
653 if (status != napi_ok) {
654 return nullptr;
655 }
656 I18nCalendarAddon *obj = nullptr;
657 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
658 if (status != napi_ok || !obj || !obj->calendar_) {
659 HILOG_ERROR_I18N("GetTimeInMillis: Get calendar object failed");
660 flag = false;
661 }
662 UDate temp = 0;
663 if (flag) {
664 temp = obj->calendar_->GetTimeInMillis();
665 }
666 napi_value result = nullptr;
667 status = napi_create_double(env, temp, &result);
668 if (status != napi_ok) {
669 HILOG_ERROR_I18N("Create UDate failed");
670 status = napi_create_double(env, 0, &result);
671 if (status != napi_ok) {
672 return nullptr;
673 }
674 }
675 return result;
676 }
677
IsWeekend(napi_env env,napi_callback_info info)678 napi_value I18nCalendarAddon::IsWeekend(napi_env env, napi_callback_info info)
679 {
680 size_t argc = 1;
681 napi_value argv[1] = { 0 };
682 napi_value thisVar = nullptr;
683 void *data = nullptr;
684 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
685 if (status != napi_ok) {
686 return nullptr;
687 }
688 I18nCalendarAddon *obj = nullptr;
689 bool isWeekEnd = false;
690 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
691 if (status != napi_ok || !obj || !obj->calendar_) {
692 HILOG_ERROR_I18N("IsWeekend: Get calendar object failed");
693 return nullptr;
694 } else if (!VariableConvertor::CheckNapiIsNull(env, argv[0])) {
695 isWeekEnd = obj->calendar_->IsWeekend();
696 } else {
697 napi_value funcGetDateInfo = nullptr;
698 status = napi_get_named_property(env, argv[0], "valueOf", &funcGetDateInfo);
699 if (status != napi_ok) {
700 HILOG_ERROR_I18N("Get method now failed");
701 return nullptr;
702 }
703 napi_value value = nullptr;
704 status = napi_call_function(env, argv[0], funcGetDateInfo, 0, nullptr, &value);
705 if (status != napi_ok) {
706 HILOG_ERROR_I18N("IsWeekend: Get milliseconds failed");
707 return nullptr;
708 }
709 double milliseconds = 0;
710 status = napi_get_value_double(env, value, &milliseconds);
711 if (status != napi_ok) {
712 HILOG_ERROR_I18N("IsWeekend: Retrieve milliseconds failed");
713 return nullptr;
714 }
715 UErrorCode error = U_ZERO_ERROR;
716 isWeekEnd = obj->calendar_->IsWeekend(milliseconds, error);
717 if (U_FAILURE(error)) {
718 return nullptr;
719 }
720 }
721 napi_value result = nullptr;
722 status = napi_get_boolean(env, isWeekEnd, &result);
723 if (status != napi_ok) {
724 HILOG_ERROR_I18N("Create boolean failed");
725 return nullptr;
726 }
727 return result;
728 }
729
CompareDays(napi_env env,napi_callback_info info)730 napi_value I18nCalendarAddon::CompareDays(napi_env env, napi_callback_info info)
731 {
732 size_t argc = 1;
733 napi_value argv[1] = { 0 };
734 napi_value thisVar = nullptr;
735 void *data = nullptr;
736 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
737 if (status != napi_ok) {
738 return nullptr;
739 }
740 napi_value result = nullptr;
741 UDate milliseconds = 0;
742 status = napi_get_date_value(env, argv[0], &milliseconds);
743 if (status != napi_ok) {
744 HILOG_ERROR_I18N("compareDays: function param is not Date");
745 return nullptr;
746 }
747
748 I18nCalendarAddon *obj = nullptr;
749 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
750 if (status != napi_ok || !obj || !obj->calendar_) {
751 HILOG_ERROR_I18N("CompareDays: Get calendar object failed");
752 status = napi_create_int32(env, 0, &result); // if error return 0
753 if (status != napi_ok) {
754 return nullptr;
755 }
756 return result;
757 }
758
759 int32_t diff_date = obj->calendar_->CompareDays(milliseconds);
760 status = napi_create_int32(env, diff_date, &result);
761 if (status != napi_ok) {
762 return nullptr;
763 }
764 return result;
765 }
766
InitCalendarContext(napi_env env,napi_callback_info info,const std::string & localeTag,CalendarType type)767 bool I18nCalendarAddon::InitCalendarContext(napi_env env, napi_callback_info info, const std::string &localeTag,
768 CalendarType type)
769 {
770 calendar_ = std::make_unique<I18nCalendar>(localeTag, type);
771 return calendar_ != nullptr;
772 }
773
GetCalendarType(napi_env env,napi_value value)774 CalendarType I18nCalendarAddon::GetCalendarType(napi_env env, napi_value value)
775 {
776 CalendarType type = CalendarType::UNDEFINED;
777 if (value != nullptr) {
778 napi_valuetype valueType = napi_valuetype::napi_undefined;
779 napi_status status = napi_typeof(env, value, &valueType);
780 if (status != napi_ok) {
781 return type;
782 }
783 if (valueType != napi_valuetype::napi_string) {
784 HILOG_ERROR_I18N("GetCalendarType: Parameter type does not match");
785 return type;
786 }
787 int32_t code = 0;
788 std::string calendarType = VariableConvertor::GetString(env, value, code);
789 if (code) {
790 return type;
791 }
792 if (g_typeMap.find(calendarType) != g_typeMap.end()) {
793 type = g_typeMap[calendarType];
794 }
795 }
796 return type;
797 }
798
SetField(napi_env env,napi_value value,UCalendarDateFields field)799 void I18nCalendarAddon::SetField(napi_env env, napi_value value, UCalendarDateFields field)
800 {
801 if (!VariableConvertor::CheckNapiIsNull(env, value)) {
802 return;
803 }
804 int32_t val = 0;
805 napi_valuetype valueType = napi_valuetype::napi_undefined;
806 napi_status status = napi_typeof(env, value, &valueType);
807 if (status != napi_ok) {
808 return;
809 }
810 if (valueType != napi_valuetype::napi_number) {
811 HILOG_ERROR_I18N("SetField: Parameter type does not match");
812 return;
813 }
814 status = napi_get_value_int32(env, value, &val);
815 if (status != napi_ok) {
816 HILOG_ERROR_I18N("SetField: Retrieve field failed");
817 return;
818 }
819 if (calendar_ != nullptr) {
820 calendar_->Set(field, val);
821 }
822 }
823
GetAddField(napi_env & env,napi_value & value,int32_t & code)824 std::string I18nCalendarAddon::GetAddField(napi_env &env, napi_value &value, int32_t &code)
825 {
826 std::string field = VariableConvertor::GetString(env, value, code);
827 if (code != 0) {
828 HILOG_ERROR_I18N("GetAddField: can't get string from js array param.");
829 return field;
830 }
831 if (g_fieldsInFunctionAdd.find(field) == g_fieldsInFunctionAdd.end()) {
832 code = 1;
833 HILOG_ERROR_I18N("Parameter rangs do not match");
834 ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "field", "a valid field", true);
835 return field;
836 }
837 return field;
838 }
839
GetDate(napi_env env,napi_value value)840 napi_value I18nCalendarAddon::GetDate(napi_env env, napi_value value)
841 {
842 if (!value) {
843 return nullptr;
844 }
845 napi_value funcGetDateInfo = nullptr;
846 napi_status status = napi_get_named_property(env, value, "valueOf", &funcGetDateInfo);
847 if (status != napi_ok) {
848 HILOG_ERROR_I18N("Get method valueOf failed");
849 return nullptr;
850 }
851 napi_value ret_value = nullptr;
852 status = napi_call_function(env, value, funcGetDateInfo, 0, nullptr, &ret_value);
853 if (status != napi_ok) {
854 HILOG_ERROR_I18N("GetDate: Get milliseconds failed");
855 return nullptr;
856 }
857 return ret_value;
858 }
859
SetMilliseconds(napi_env env,napi_value value)860 void I18nCalendarAddon::SetMilliseconds(napi_env env, napi_value value)
861 {
862 if (!value) {
863 return;
864 }
865 double milliseconds = 0;
866 napi_valuetype valueType = napi_valuetype::napi_undefined;
867 napi_status status = napi_typeof(env, value, &valueType);
868 if (status != napi_ok) {
869 return;
870 }
871 if (valueType != napi_valuetype::napi_number) {
872 HILOG_ERROR_I18N("SetMilliseconds: Parameter type does not match");
873 return;
874 }
875 status = napi_get_value_double(env, value, &milliseconds);
876 if (status != napi_ok) {
877 HILOG_ERROR_I18N("SetMilliseconds: Retrieve milliseconds failed");
878 return;
879 }
880 if (calendar_ != nullptr) {
881 calendar_->SetTime(milliseconds);
882 }
883 }
884
885 } // namespace I18n
886 } // namespace Global
887 } // namespace OHOS