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