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 "napi_system_date_time.h"
17 
18 #include "parameters.h"
19 #include "napi_work.h"
20 #include "napi_utils.h"
21 #include "time_hilog.h"
22 #include "time_service_client.h"
23 
24 using namespace OHOS::MiscServices;
25 
26 namespace OHOS {
27 namespace MiscServices {
28 namespace Time {
29 
30 constexpr int64_t SECONDS_TO_NANO = 1000000000;
31 constexpr int64_t SECONDS_TO_MILLI = 1000;
32 constexpr int64_t NANO_TO_MILLI = SECONDS_TO_NANO / SECONDS_TO_MILLI;
33 constexpr int32_t STARTUP = 0;
34 constexpr int32_t ACTIVE = 1;
35 const std::string TIMEZONE_KEY = "persist.time.timezone";
36 
SystemDateTimeInit(napi_env env,napi_value exports)37 napi_value NapiSystemDateTime::SystemDateTimeInit(napi_env env, napi_value exports)
38 {
39     napi_value timeType = nullptr;
40     napi_value startup = nullptr;
41     napi_value active = nullptr;
42     NAPI_CALL(env, napi_create_int32(env, STARTUP, &startup));
43     NAPI_CALL(env, napi_create_int32(env, ACTIVE, &active));
44     NAPI_CALL(env, napi_create_object(env, &timeType));
45     NAPI_CALL(env, napi_set_named_property(env, timeType, "STARTUP", startup));
46     NAPI_CALL(env, napi_set_named_property(env, timeType, "ACTIVE", active));
47 
48     napi_property_descriptor descriptors[] = {
49         DECLARE_NAPI_STATIC_FUNCTION("setTime", SetTime),
50         DECLARE_NAPI_STATIC_FUNCTION("getCurrentTime", GetCurrentTime),
51         DECLARE_NAPI_STATIC_FUNCTION("getRealActiveTime", GetRealActiveTime),
52         DECLARE_NAPI_STATIC_FUNCTION("getRealTime", GetRealTime),
53         DECLARE_NAPI_STATIC_FUNCTION("getTime", GetTime),
54         DECLARE_NAPI_STATIC_FUNCTION("updateNtpTime", UpdateNtpTime),
55         DECLARE_NAPI_STATIC_FUNCTION("getNtpTime", GetNtpTime),
56         DECLARE_NAPI_STATIC_FUNCTION("setDate", SetDate),
57         DECLARE_NAPI_STATIC_FUNCTION("getDate", GetDate),
58         DECLARE_NAPI_STATIC_FUNCTION("setTimezone", SetTimezone),
59         DECLARE_NAPI_STATIC_FUNCTION("getTimezone", GetTimezone),
60         DECLARE_NAPI_STATIC_FUNCTION("getUptime", GetUptime),
61         DECLARE_NAPI_STATIC_FUNCTION("getTimezoneSync", GetTimezoneSync),
62         DECLARE_NAPI_STATIC_PROPERTY("TimeType", timeType),
63     };
64 
65     napi_status status =
66         napi_define_properties(env, exports, sizeof(descriptors) / sizeof(napi_property_descriptor), descriptors);
67     if (status != napi_ok) {
68         TIME_HILOGE(TIME_MODULE_JS_NAPI, "define manager properties failed, status=%{public}d", status);
69         return NapiUtils::GetUndefinedValue(env);
70     }
71     return exports;
72 }
73 
SetTime(napi_env env,napi_callback_info info)74 napi_value NapiSystemDateTime::SetTime(napi_env env, napi_callback_info info)
75 {
76     struct SetTimeContext : public ContextBase {
77         int64_t time = 0;
78     };
79     auto *setTimeContext = new SetTimeContext();
80     auto inputParser = [env, setTimeContext](size_t argc, napi_value *argv) {
81         CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, setTimeContext, argc >= ARGC_ONE,
82             "Mandatory parameters are left unspecified", JsErrorCode::PARAMETER_ERROR);
83         setTimeContext->status = napi_get_value_int64(env, argv[ARGV_FIRST], &setTimeContext->time);
84         CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, setTimeContext, setTimeContext->status == napi_ok,
85             "The type of 'time' must be number", JsErrorCode::PARAMETER_ERROR);
86         setTimeContext->status = napi_ok;
87     };
88     setTimeContext->GetCbInfo(env, info, inputParser);
89     auto executor = [setTimeContext]() {
90         auto innerCode = TimeServiceClient::GetInstance()->SetTimeV9(setTimeContext->time);
91         if (innerCode != JsErrorCode::ERROR_OK) {
92             setTimeContext->errCode = innerCode;
93             setTimeContext->status = napi_generic_failure;
94         }
95     };
96     auto complete = [env](napi_value &output) { output = NapiUtils::GetUndefinedValue(env); };
97     return NapiWork::AsyncEnqueue(env, setTimeContext, "SetTime", executor, complete);
98 }
99 
SetDate(napi_env env,napi_callback_info info)100 napi_value NapiSystemDateTime::SetDate(napi_env env, napi_callback_info info)
101 {
102     struct SetDateContext : public ContextBase {
103         int64_t time = 0;
104     };
105     auto *setDateContext = new SetDateContext();
106     auto inputParser = [env, setDateContext](size_t argc, napi_value *argv) {
107         CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, setDateContext, argc >= ARGC_ONE,
108             "Mandatory parameters are left unspecified", JsErrorCode::PARAMETER_ERROR);
109         napi_valuetype valueType = napi_undefined;
110         napi_typeof(env, argv[ARGV_FIRST], &valueType);
111         if (valueType == napi_number) {
112             napi_get_value_int64(env, argv[ARGV_FIRST], &setDateContext->time);
113             CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, setDateContext, setDateContext->time >= 0,
114                 "date number must >= 0", JsErrorCode::PARAMETER_ERROR);
115         } else {
116             bool hasProperty = false;
117             napi_valuetype resValueType = napi_undefined;
118             napi_has_named_property(env, argv[ARGV_FIRST], "getTime", &hasProperty);
119             CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, setDateContext, hasProperty,
120                 "The type of 'date' must be Date", JsErrorCode::PARAMETER_ERROR);
121             napi_value getTimeFunc = nullptr;
122             napi_get_named_property(env, argv[0], "getTime", &getTimeFunc);
123             napi_value getTimeResult = nullptr;
124             napi_call_function(env, argv[0], getTimeFunc, 0, nullptr, &getTimeResult);
125             napi_typeof(env, getTimeResult, &resValueType);
126             CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, setDateContext, resValueType == napi_number,
127                 "The type of 'date' must be Date", JsErrorCode::PARAMETER_ERROR);
128             setDateContext->status = napi_get_value_int64(env, getTimeResult, &setDateContext->time);
129         }
130         CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, setDateContext, setDateContext->status == napi_ok,
131             "The type of 'date' must be Date", JsErrorCode::PARAMETER_ERROR);
132         setDateContext->status = napi_ok;
133     };
134     setDateContext->GetCbInfo(env, info, inputParser);
135     auto executor = [setDateContext]() {
136         auto innerCode = TimeServiceClient::GetInstance()->SetTimeV9(setDateContext->time);
137         if (innerCode != JsErrorCode::ERROR_OK) {
138             setDateContext->errCode = innerCode;
139             setDateContext->status = napi_generic_failure;
140         }
141     };
142     auto complete = [env](napi_value &output) { output = NapiUtils::GetUndefinedValue(env); };
143     return NapiWork::AsyncEnqueue(env, setDateContext, "SetDate", executor, complete);
144 }
145 
GetRealActiveTime(napi_env env,napi_callback_info info)146 napi_value NapiSystemDateTime::GetRealActiveTime(napi_env env, napi_callback_info info)
147 {
148     struct GetRealActiveTimeContext : public ContextBase {
149         int64_t time = 0;
150         bool isNano = false;
151     };
152     auto *getRealActiveTimeContext = new GetRealActiveTimeContext();
153     auto inputParser = [env, getRealActiveTimeContext](size_t argc, napi_value *argv) {
154         if (argc >= ARGC_ONE) {
155             napi_valuetype valueType = napi_undefined;
156             napi_typeof(env, argv[ARGV_FIRST], &valueType);
157             if (valueType == napi_boolean) {
158                 getRealActiveTimeContext->status =
159                     napi_get_value_bool(env, argv[ARGV_FIRST], &getRealActiveTimeContext->isNano);
160                 CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, getRealActiveTimeContext,
161                     getRealActiveTimeContext->status == napi_ok, "invalid isNano", JsErrorCode::PARAMETER_ERROR);
162             }
163         }
164         getRealActiveTimeContext->status = napi_ok;
165     };
166     getRealActiveTimeContext->GetCbInfo(env, info, inputParser);
167     auto executor = [getRealActiveTimeContext]() {
168         int32_t innerCode;
169         if (getRealActiveTimeContext->isNano) {
170             innerCode = TimeServiceClient::GetInstance()->GetMonotonicTimeNs(getRealActiveTimeContext->time);
171         } else {
172             innerCode = TimeServiceClient::GetInstance()->GetMonotonicTimeMs(getRealActiveTimeContext->time);
173         }
174         if (innerCode != JsErrorCode::ERROR_OK) {
175             getRealActiveTimeContext->errCode = NapiUtils::ConvertErrorCode(innerCode);
176             getRealActiveTimeContext->status = napi_generic_failure;
177         }
178     };
179     auto complete = [env, getRealActiveTimeContext](napi_value &output) {
180         getRealActiveTimeContext->status = napi_create_int64(env, getRealActiveTimeContext->time, &output);
181         CHECK_STATUS_RETURN_VOID(TIME_MODULE_JS_NAPI, getRealActiveTimeContext,
182             "convert native object to javascript object failed", JsErrorCode::ERROR);
183     };
184     return NapiWork::AsyncEnqueue(env, getRealActiveTimeContext, "GetRealActiveTime", executor, complete);
185 }
186 
GetCurrentTime(napi_env env,napi_callback_info info)187 napi_value NapiSystemDateTime::GetCurrentTime(napi_env env, napi_callback_info info)
188 {
189     struct GetCurrentTimeContext : public ContextBase {
190         int64_t time = 0;
191         bool isNano = false;
192     };
193     auto *getCurrentTimeContext = new GetCurrentTimeContext();
194     auto inputParser = [env, getCurrentTimeContext](size_t argc, napi_value *argv) {
195         if (argc >= ARGC_ONE) {
196             napi_valuetype valueType = napi_undefined;
197             napi_typeof(env, argv[ARGV_FIRST], &valueType);
198             if (valueType == napi_boolean) {
199                 getCurrentTimeContext->status =
200                     napi_get_value_bool(env, argv[ARGV_FIRST], &getCurrentTimeContext->isNano);
201                 CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, getCurrentTimeContext,
202                     getCurrentTimeContext->status == napi_ok, "invalid isNano", JsErrorCode::PARAMETER_ERROR);
203             }
204         }
205         getCurrentTimeContext->status = napi_ok;
206     };
207     getCurrentTimeContext->GetCbInfo(env, info, inputParser);
208     auto executor = [getCurrentTimeContext]() {
209         int32_t innerCode;
210         if (getCurrentTimeContext->isNano) {
211             innerCode = TimeServiceClient::GetInstance()->GetWallTimeNs(getCurrentTimeContext->time);
212         } else {
213             innerCode = TimeServiceClient::GetInstance()->GetWallTimeMs(getCurrentTimeContext->time);
214         }
215         if (innerCode != JsErrorCode::ERROR_OK) {
216             getCurrentTimeContext->errCode = innerCode;
217             getCurrentTimeContext->status = napi_generic_failure;
218         }
219     };
220     auto complete = [getCurrentTimeContext, env](napi_value &output) {
221         getCurrentTimeContext->status = napi_create_int64(env, getCurrentTimeContext->time, &output);
222         CHECK_STATUS_RETURN_VOID(TIME_MODULE_JS_NAPI, getCurrentTimeContext,
223             "convert native object to javascript object failed", JsErrorCode::ERROR);
224     };
225     return NapiWork::AsyncEnqueue(env, getCurrentTimeContext, "GetCurrentTime", executor, complete);
226 }
227 
GetTime(napi_env env,napi_callback_info info)228 napi_value NapiSystemDateTime::GetTime(napi_env env, napi_callback_info info)
229 {
230     struct GetTimeContext : public ContextBase {
231         int64_t time = 0;
232         bool isNano = false;
233     };
234     auto *getTimeContext = new GetTimeContext();
235     auto inputParser = [env, getTimeContext](size_t argc, napi_value *argv) {
236         if (argc >= ARGC_ONE) {
237             napi_valuetype valueType = napi_undefined;
238             napi_typeof(env, argv[ARGV_FIRST], &valueType);
239             if (valueType == napi_boolean) {
240                 getTimeContext->status = napi_get_value_bool(env, argv[ARGV_FIRST], &getTimeContext->isNano);
241                 CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, getTimeContext, getTimeContext->status == napi_ok,
242                                        "invalid isNano", JsErrorCode::PARAMETER_ERROR);
243             }
244         }
245         getTimeContext->status = napi_ok;
246     };
247     getTimeContext->GetCbInfo(env, info, inputParser, true);
248     auto executor = [getTimeContext]() {
249         int32_t innerCode = GetDeviceTime(CLOCK_REALTIME, getTimeContext->isNano, getTimeContext->time);
250         if (innerCode != JsErrorCode::ERROR_OK) {
251             getTimeContext->errCode = innerCode;
252             getTimeContext->status = napi_generic_failure;
253         }
254     };
255     auto complete = [getTimeContext](napi_value &output) {
256         getTimeContext->status = napi_create_int64(getTimeContext->env, getTimeContext->time, &output);
257         CHECK_STATUS_RETURN_VOID(TIME_MODULE_JS_NAPI, getTimeContext,
258                                  "convert native object to javascript object failed", JsErrorCode::ERROR);
259     };
260     return NapiWork::SyncEnqueue(env, getTimeContext, "GetTime", executor, complete);
261 }
262 
GetRealTime(napi_env env,napi_callback_info info)263 napi_value NapiSystemDateTime::GetRealTime(napi_env env, napi_callback_info info)
264 {
265     struct GetRealTimeContext : public ContextBase {
266         int64_t time = 0;
267         bool isNano = false;
268     };
269     auto *getRealTimeContext = new GetRealTimeContext();
270     auto inputParser = [env, getRealTimeContext](size_t argc, napi_value *argv) {
271         if (argc >= ARGC_ONE) {
272             napi_valuetype valueType = napi_undefined;
273             napi_typeof(env, argv[ARGV_FIRST], &valueType);
274             if (valueType == napi_boolean) {
275                 getRealTimeContext->status = napi_get_value_bool(env, argv[ARGV_FIRST], &getRealTimeContext->isNano);
276                 CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, getRealTimeContext, getRealTimeContext->status == napi_ok,
277                     "invalid isNano", JsErrorCode::PARAMETER_ERROR);
278             }
279         }
280         getRealTimeContext->status = napi_ok;
281     };
282     getRealTimeContext->GetCbInfo(env, info, inputParser);
283     auto executor = [getRealTimeContext]() {
284         int32_t innerCode;
285         if (getRealTimeContext->isNano) {
286             innerCode = TimeServiceClient::GetInstance()->GetBootTimeNs(getRealTimeContext->time);
287         } else {
288             innerCode = TimeServiceClient::GetInstance()->GetBootTimeMs(getRealTimeContext->time);
289         }
290         if (innerCode != JsErrorCode::ERROR_OK) {
291             getRealTimeContext->errCode = innerCode;
292             getRealTimeContext->status = napi_generic_failure;
293         }
294     };
295     auto complete = [getRealTimeContext](napi_value &output) {
296         getRealTimeContext->status = napi_create_int64(getRealTimeContext->env, getRealTimeContext->time, &output);
297         CHECK_STATUS_RETURN_VOID(TIME_MODULE_JS_NAPI, getRealTimeContext,
298             "convert native object to javascript object failed", JsErrorCode::ERROR);
299     };
300     return NapiWork::AsyncEnqueue(env, getRealTimeContext, "GetRealTime", executor, complete);
301 }
302 
GetUptime(napi_env env,napi_callback_info info)303 napi_value NapiSystemDateTime::GetUptime(napi_env env, napi_callback_info info)
304 {
305     struct GetUpTimeContext : public ContextBase {
306         int64_t time = 0;
307         int32_t timeType = STARTUP;
308         bool isNanoseconds = false;
309     };
310     auto *getUpTimeContext = new GetUpTimeContext();
311     auto inputParser = [env, getUpTimeContext](size_t argc, napi_value *argv) {
312         CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, getUpTimeContext, argc >= ARGC_ONE,
313             "Mandatory parameters are left unspecified", JsErrorCode::PARAMETER_ERROR);
314         getUpTimeContext->status = napi_get_value_int32(env, argv[ARGV_FIRST], &getUpTimeContext->timeType);
315         CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, getUpTimeContext, getUpTimeContext->status == napi_ok,
316             "The type of 'timeType' must be number or enum", JsErrorCode::PARAMETER_ERROR);
317         CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, getUpTimeContext,
318             (getUpTimeContext->timeType >= STARTUP && getUpTimeContext->timeType <= ACTIVE),
319             "The 'timeType' must be 'STARTUP' or 'ACTIVE' or 0 or 1", JsErrorCode::PARAMETER_ERROR);
320         if (argc >= ARGC_TWO) {
321             napi_valuetype valueType = napi_undefined;
322             napi_typeof(env, argv[ARGV_SECOND], &valueType);
323             if (valueType == napi_boolean) {
324                 getUpTimeContext->status =
325                     napi_get_value_bool(env, argv[ARGV_SECOND], &getUpTimeContext->isNanoseconds);
326                 CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, getUpTimeContext, getUpTimeContext->status == napi_ok,
327                     "get isNanoseconds failed", JsErrorCode::PARAMETER_ERROR);
328             }
329         }
330         getUpTimeContext->status = napi_ok;
331     };
332     getUpTimeContext->GetCbInfo(env, info, inputParser, true);
333     auto executor = [getUpTimeContext]() {
334         int32_t innerCode;
335         if (getUpTimeContext->timeType == STARTUP) {
336             innerCode = GetDeviceTime(CLOCK_BOOTTIME, getUpTimeContext->isNanoseconds, getUpTimeContext->time);
337         } else {
338             innerCode = GetDeviceTime(CLOCK_MONOTONIC, getUpTimeContext->isNanoseconds, getUpTimeContext->time);
339         }
340         if (innerCode != JsErrorCode::ERROR_OK) {
341             getUpTimeContext->errCode = innerCode;
342             getUpTimeContext->status = napi_generic_failure;
343         }
344     };
345     auto complete = [getUpTimeContext](napi_value &output) {
346         getUpTimeContext->status = napi_create_int64(getUpTimeContext->env, getUpTimeContext->time, &output);
347         CHECK_STATUS_RETURN_VOID(TIME_MODULE_JS_NAPI, getUpTimeContext,
348                                  "convert native object to javascript object failed", JsErrorCode::ERROR);
349     };
350     return NapiWork::SyncEnqueue(env, getUpTimeContext, "GetUpTime", executor, complete);
351 }
352 
GetDate(napi_env env,napi_callback_info info)353 napi_value NapiSystemDateTime::GetDate(napi_env env, napi_callback_info info)
354 {
355     struct GetDateContext : public ContextBase {
356         int64_t time = 0;
357     };
358     auto *getDateContext = new GetDateContext();
359     auto inputParser = [getDateContext](size_t argc, napi_value *argv) { getDateContext->status = napi_ok; };
360     getDateContext->GetCbInfo(env, info, inputParser);
361     auto executor = [getDateContext]() {
362         auto innerCode = TimeServiceClient::GetInstance()->GetWallTimeMs(getDateContext->time);
363         if (innerCode != JsErrorCode::ERROR_OK) {
364             getDateContext->errCode = innerCode;
365             getDateContext->status = napi_generic_failure;
366         }
367     };
368     auto complete = [env, getDateContext](napi_value &output) {
369         getDateContext->status = napi_create_date(env, getDateContext->time, &output);
370         CHECK_STATUS_RETURN_VOID(TIME_MODULE_JS_NAPI, getDateContext,
371             "convert native object to javascript object failed", JsErrorCode::ERROR);
372     };
373 
374     return NapiWork::AsyncEnqueue(env, getDateContext, "GetDate", executor, complete);
375 }
376 
SetTimezone(napi_env env,napi_callback_info info)377 napi_value NapiSystemDateTime::SetTimezone(napi_env env, napi_callback_info info)
378 {
379     struct SetTimezoneContext : public ContextBase {
380         std::string timezone;
381     };
382     auto *setTimezoneContext = new SetTimezoneContext();
383     auto inputParser = [env, setTimezoneContext](size_t argc, napi_value *argv) {
384         CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, setTimezoneContext, argc >= ARGC_ONE,
385             "Mandatory parameters are left unspecified", JsErrorCode::PARAMETER_ERROR);
386         setTimezoneContext->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], setTimezoneContext->timezone);
387         CHECK_ARGS_RETURN_VOID(TIME_MODULE_JS_NAPI, setTimezoneContext, setTimezoneContext->status == napi_ok,
388             "The type of 'timezone' must be string", JsErrorCode::PARAMETER_ERROR);
389         setTimezoneContext->status = napi_ok;
390     };
391     setTimezoneContext->GetCbInfo(env, info, inputParser);
392     auto executor = [setTimezoneContext]() {
393         auto innerCode = TimeServiceClient::GetInstance()->SetTimeZoneV9(setTimezoneContext->timezone);
394         if (innerCode != JsErrorCode::ERROR_OK) {
395             setTimezoneContext->errCode = innerCode;
396             setTimezoneContext->status = napi_generic_failure;
397         }
398     };
399     auto complete = [env](napi_value &output) { output = NapiUtils::GetUndefinedValue(env); };
400     return NapiWork::AsyncEnqueue(env, setTimezoneContext, "SetTimezone", executor, complete);
401 }
402 
GetTimezone(napi_env env,napi_callback_info info)403 napi_value NapiSystemDateTime::GetTimezone(napi_env env, napi_callback_info info)
404 {
405     struct GetTimezoneContext : public ContextBase {
406         std::string timezone;
407     };
408     auto *getTimezoneContext = new GetTimezoneContext();
409     auto inputParser = [getTimezoneContext](size_t argc, napi_value *argv) {
410         getTimezoneContext->status = napi_ok;
411     };
412     getTimezoneContext->GetCbInfo(env, info, inputParser);
413 
414     auto executor = [getTimezoneContext]() {
415         auto innerCode = TimeServiceClient::GetInstance()->GetTimeZone(getTimezoneContext->timezone);
416         if (innerCode != JsErrorCode::ERROR_OK) {
417             getTimezoneContext->errCode = innerCode;
418             getTimezoneContext->status = napi_generic_failure;
419         }
420     };
421     auto complete = [env, getTimezoneContext](napi_value &output) {
422         getTimezoneContext->status = napi_create_string_utf8(env, getTimezoneContext->timezone.c_str(),
423             getTimezoneContext->timezone.size(), &output);
424         TIME_HILOGI(TIME_MODULE_JS_NAPI, "%{public}s, ", getTimezoneContext->timezone.c_str());
425         CHECK_STATUS_RETURN_VOID(TIME_MODULE_JS_NAPI, getTimezoneContext,
426             "convert native object to javascript object failed", JsErrorCode::ERROR);
427     };
428     return NapiWork::AsyncEnqueue(env, getTimezoneContext, "GetTimezone", executor, complete);
429 }
430 
GetTimezoneSync(napi_env env,napi_callback_info info)431 napi_value NapiSystemDateTime::GetTimezoneSync(napi_env env, napi_callback_info info)
432 {
433     struct GetTimezoneContext : public ContextBase {
434         std::string timezone;
435     };
436     auto *getTimezoneContext = new GetTimezoneContext();
437     auto inputParser = [getTimezoneContext](size_t argc, napi_value *argv) { getTimezoneContext->status = napi_ok; };
438     getTimezoneContext->GetCbInfo(env, info, inputParser, true);
439 
440     auto executor = [getTimezoneContext]() {
441         auto innerCode = GetTimezone(getTimezoneContext->timezone);
442         if (innerCode != JsErrorCode::ERROR_OK) {
443             getTimezoneContext->errCode = innerCode;
444             getTimezoneContext->status = napi_generic_failure;
445         }
446     };
447     auto complete = [env, getTimezoneContext](napi_value &output) {
448         getTimezoneContext->status = napi_create_string_utf8(env, getTimezoneContext->timezone.c_str(),
449             getTimezoneContext->timezone.size(), &output);
450         CHECK_STATUS_RETURN_VOID(TIME_MODULE_JS_NAPI, getTimezoneContext,
451             "convert native object to javascript object failed", JsErrorCode::ERROR);
452     };
453     return NapiWork::SyncEnqueue(env, getTimezoneContext, "GetTimezone", executor, complete);
454 }
455 
UpdateNtpTime(napi_env env,napi_callback_info info)456 napi_value NapiSystemDateTime::UpdateNtpTime(napi_env env, napi_callback_info info)
457 {
458     struct UpdateNtpTime : public ContextBase {
459         int64_t time = 0;
460     };
461     auto *updateNtpTimeContext = new UpdateNtpTime();
462     auto inputParser = [env, updateNtpTimeContext](size_t argc, napi_value *argv) {
463         updateNtpTimeContext->status = napi_ok;
464     };
465     updateNtpTimeContext->GetCbInfo(env, info, inputParser);
466 
467     auto executor = [updateNtpTimeContext]() {
468         int32_t innerCode = TimeServiceClient::GetInstance()->GetNtpTimeMs(updateNtpTimeContext->time);
469         if (innerCode != JsErrorCode::ERROR_OK) {
470             updateNtpTimeContext->errCode = innerCode;
471             updateNtpTimeContext->status = napi_generic_failure;
472         }
473     };
474     auto complete = [env](napi_value &output) {
475         output = NapiUtils::GetUndefinedValue(env);
476     };
477     return NapiWork::AsyncEnqueue(env, updateNtpTimeContext, "UpdateNtpTime", executor, complete);
478 }
479 
GetNtpTime(napi_env env,napi_callback_info info)480 napi_value NapiSystemDateTime::GetNtpTime(napi_env env, napi_callback_info info)
481 {
482     struct GetNtpTimeContext : public ContextBase {
483         int64_t time = 0;
484     };
485     auto *getNtpTimeContext = new GetNtpTimeContext();
486     auto inputParser = [env, getNtpTimeContext](size_t argc, napi_value *argv) {
487         getNtpTimeContext->status = napi_ok;
488     };
489     getNtpTimeContext->GetCbInfo(env, info, inputParser);
490 
491     auto executor = [getNtpTimeContext]() {
492         int32_t innerCode = TimeServiceClient::GetInstance()->GetRealTimeMs(getNtpTimeContext->time);
493         if (innerCode != JsErrorCode::ERROR_OK) {
494             getNtpTimeContext->errCode = innerCode;
495             getNtpTimeContext->status = napi_generic_failure;
496         }
497     };
498     auto complete = [getNtpTimeContext](napi_value &output) {
499         getNtpTimeContext->status = napi_create_int64(getNtpTimeContext->env, getNtpTimeContext->time, &output);
500         CHECK_STATUS_RETURN_VOID(TIME_MODULE_JS_NAPI, getNtpTimeContext,
501             "convert native object to javascript object failed", JsErrorCode::ERROR);
502     };
503     return NapiWork::SyncEnqueue(env, getNtpTimeContext, "GetNtpTime", executor, complete);
504 }
505 
GetDeviceTime(clockid_t clockId,bool isNano,int64_t & time)506 int32_t NapiSystemDateTime::GetDeviceTime(clockid_t clockId, bool isNano, int64_t &time)
507 {
508     struct timespec tv {};
509     if (clock_gettime(clockId, &tv) < 0) {
510         TIME_HILOGE(TIME_MODULE_SERVICE, "failed clock_gettime, errno: %{public}s", strerror(errno));
511         return ERROR;
512     }
513 
514     if (isNano) {
515         time = tv.tv_sec * SECONDS_TO_NANO + tv.tv_nsec;
516     } else {
517         time = tv.tv_sec * SECONDS_TO_MILLI + tv.tv_nsec / NANO_TO_MILLI;
518     }
519     return ERROR_OK;
520 }
521 
GetTimezone(std::string & timezone)522 int32_t NapiSystemDateTime::GetTimezone(std::string &timezone)
523 {
524     timezone = system::GetParameter(TIMEZONE_KEY, "Asia/Shanghai");
525     if (timezone.empty()) {
526         TIME_HILOGW(TIME_MODULE_SERVICE, "No found timezone from system parameter.");
527         return ERROR;
528     }
529     return ERROR_OK;
530 }
531 } // namespace Time
532 } // namespace MiscServices
533 } // namespace OHOS