1 /*
2 * Copyright (C) 2021 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 "time_zone_info.h"
17
18 namespace OHOS {
19 namespace MiscServices {
20 namespace {
21 constexpr const char *TIMEZONE_KEY = "persist.time.timezone";
22 const int TIMEZONE_OK = 0;
23 const int CONFIG_LEN = 35;
24 const int HOUR_TO_MILLI = 60;
25 }
26
TimeZoneInfo()27 TimeZoneInfo::TimeZoneInfo()
28 {
29 std::vector<struct zoneInfoEntry> timezoneList = { { "Antarctica/McMurdo", "AQ", 12 },
30 { "America/Argentina/Buenos_Aires", "AR", -3 }, { "Australia/Sydney", "AU", 10 },
31 { "America/Noronha", "BR", -2 }, { "America/St_Johns", "CA", -3 }, { "Africa/Kinshasa", "CD", 1 },
32 { "America/Santiago", "CL", -3 }, { "Asia/Shanghai", "CN", 8 }, { "Asia/Nicosia", "CY", 3 },
33 { "Europe/Berlin", "DE", 2 }, { "America/Guayaquil", "CEST", -5 }, { "Europe/Madrid", "ES", 2 },
34 { "Pacific/Pohnpei", "FM", 11 }, { "America/Godthab", "GL", -2 }, { "Asia/Jakarta", "ID", 7 },
35 { "Pacific/Tarawa", "KI", 12 }, { "Asia/Almaty", "KZ", 6 }, { "Pacific/Majuro", "MH", 12 },
36 { "Asia/Ulaanbaatar", "MN", 8 }, { "America/Mexico_City", "MX", -5 }, { "Asia/Kuala_Lumpur", "MY", 8 },
37 { "Pacific/Auckland", "NZ", 12 }, { "Pacific/Tahiti", "PF", -10 }, { "Pacific/Port_Moresby", "PG", 10 },
38 { "Asia/Gaza", "PS", 3 }, { "Europe/Lisbon", "PT", 1 }, { "Europe/Moscow", "RU", 3 },
39 { "Europe/Kiev", "UA", 3 }, { "Pacific/Wake", "UM", 12 }, { "America/New_York", "US", -4 },
40 { "Asia/Tashkent", "UZ", 5 } };
41
42 for (const auto &tz : timezoneList) {
43 timezoneInfoMap_[tz.ID] = tz;
44 }
45 }
46
~TimeZoneInfo()47 TimeZoneInfo::~TimeZoneInfo()
48 {
49 timezoneInfoMap_.clear();
50 }
51
Init()52 void TimeZoneInfo::Init()
53 {
54 TIME_HILOGD(TIME_MODULE_SERVICE, "Start.");
55 char value[CONFIG_LEN] = "Asia/Shanghai";
56 if (GetParameter(TIMEZONE_KEY, "", value, CONFIG_LEN) < TIMEZONE_OK) {
57 TIME_HILOGW(TIME_MODULE_SERVICE, "No found timezone from system parameter.");
58 }
59
60 if (!SetTimezoneToKernel(value)) {
61 TIME_HILOGE(TIME_MODULE_SERVICE, "Init Set kernel failed.");
62 }
63 curTimezoneId_ = value;
64 TIME_HILOGI(TIME_MODULE_SERVICE, "Timezone value: %{public}s", value);
65 }
66
SetTimezone(std::string timezoneId)67 bool TimeZoneInfo::SetTimezone(std::string timezoneId)
68 {
69 if (curTimezoneId_ == timezoneId) {
70 TIME_HILOGI(TIME_MODULE_SERVICE, "Same Timezone has been set.");
71 return true;
72 }
73
74 auto errNo = SetParameter(TIMEZONE_KEY, timezoneId.c_str());
75 if (errNo > TIMEZONE_OK) {
76 TIME_HILOGE(TIME_MODULE_SERVICE, "SetTimezone timezoneId: %{public}d: %{public}s", errNo, timezoneId.c_str());
77 return false;
78 }
79
80 if (!SetTimezoneToKernel(timezoneId)) {
81 TIME_HILOGE(TIME_MODULE_SERVICE, "SetTimezone Set kernel failed.");
82 return false;
83 }
84 curTimezoneId_ = timezoneId;
85 return true;
86 }
87
GetTimezone(std::string & timezoneId)88 bool TimeZoneInfo::GetTimezone(std::string &timezoneId)
89 {
90 timezoneId = curTimezoneId_;
91 return true;
92 }
93
SetTimezoneToKernel(std::string timezoneId)94 bool TimeZoneInfo::SetTimezoneToKernel(std::string timezoneId)
95 {
96 auto itEntry = timezoneInfoMap_.find(timezoneId);
97 if (itEntry != timezoneInfoMap_.end()) {
98 auto offset = itEntry->second.utcOffsetHours;
99 struct timezone tz;
100 tz.tz_minuteswest = offset * HOUR_TO_MILLI;
101 tz.tz_dsttime = 0;
102
103 int result = settimeofday(NULL, &tz);
104 if (result < 0) {
105 TIME_HILOGI(TIME_MODULE_SERVICE, "Settimeofday timezone fail: %{public}d.", result);
106 return false;
107 } else {
108 TIME_HILOGI(TIME_MODULE_SERVICE, "Timezone offset: %{public}d", offset);
109 return true;
110 }
111 }
112 return false;
113 }
114 }
115 }