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