• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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