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 "base/utils/time_util.h"
17
18 #include <iomanip>
19 #include <sstream>
20 #include <sys/time.h>
21 #include "base/utils/utils.h"
22
23 namespace OHOS::Ace {
24 namespace {
25
26 constexpr int64_t SEC_TO_MICROSEC = 1000000;
27 constexpr int64_t SEC_TO_NANOSEC = 1000000000;
28 constexpr int64_t MICROSEC_TO_NANOSEC = 1000;
29 constexpr int64_t SEC_TO_MILLISEC = 1000;
30 constexpr int64_t MILLISEC_TO_MICROSEC = 1000;
31 constexpr int32_t HOURS_WEST_GEOGRAPHICAL_LOWER_LIMIT = -12;
32 constexpr int32_t HOURS_WEST_LOWER_LIMIT = -14;
33 constexpr int32_t HOURS_WEST_UPPER_LIMIT = 12;
34 constexpr int32_t TOTAL_SECONDS_OF_DAY = 24 * 60 * 60;
35 constexpr int32_t TOTAL_SECONDS_OF_HOUR = 60 * 60;
36 constexpr int32_t TOTAL_SECONDS_OF_MINUTE = 60;
37 constexpr int32_t TOTAL_MINUTE_OF_HOUR = 60;
38 constexpr int32_t TWENTY_FOUR_HOUR_BASE = 24;
39 constexpr int32_t TWELVE_HOUR_BASE = 12;
40 constexpr int32_t DAY_TIME_LOWER_LIMIT = 6;
41 constexpr int32_t DAY_TIME_UPPER_LIMIT = 18;
42 constexpr int32_t MAX_TIME_STR_LEN = 64;
43 } // namespace
44
GetMicroTickCount()45 int64_t GetMicroTickCount()
46 {
47 struct timespec ts;
48 clock_gettime(CLOCK_MONOTONIC, &ts);
49 return (ts.tv_sec * SEC_TO_MICROSEC + ts.tv_nsec / MICROSEC_TO_NANOSEC);
50 }
51
GetSysTimestamp()52 int64_t GetSysTimestamp()
53 {
54 struct timespec ts;
55 clock_gettime(CLOCK_MONOTONIC, &ts);
56 return ts.tv_sec * SEC_TO_NANOSEC + ts.tv_nsec;
57 }
58
GetCurrentTimestamp()59 int64_t GetCurrentTimestamp()
60 {
61 struct timeval currentTime;
62 gettimeofday(¤tTime, nullptr);
63 return static_cast<int64_t>(currentTime.tv_sec) * SEC_TO_MILLISEC + currentTime.tv_usec / MILLISEC_TO_MICROSEC;
64 }
65
GetCurrentTimestampMicroSecond()66 int64_t GetCurrentTimestampMicroSecond()
67 {
68 struct timeval currentTime;
69 gettimeofday(¤tTime, nullptr);
70 return static_cast<int64_t>(currentTime.tv_sec) * SEC_TO_MILLISEC * MILLISEC_TO_MICROSEC + currentTime.tv_usec;
71 }
72
ConvertTimestampToStr(int64_t timestamp)73 std::string ConvertTimestampToStr(int64_t timestamp)
74 {
75 char timeStr[MAX_TIME_STR_LEN];
76 // timestamp is in millisecond unit, divide 1000 to second
77 auto t = static_cast<std::time_t>(timestamp / SEC_TO_MILLISEC);
78 auto local = std::localtime(&t);
79 if (!local) {
80 return "";
81 }
82 std::strftime(timeStr, MAX_TIME_STR_LEN, "%Y-%m-%d %H:%M:%S", local);
83 std::stringstream oss;
84 // milliseconds in timestr should be 3 characters length
85 oss << timeStr << "." << std::setw(3) << std::setfill('0') << (timestamp % SEC_TO_MILLISEC);
86 return oss.str();
87 }
88
GetTimeOfNow(int32_t hoursWest)89 TimeOfNow GetTimeOfNow(int32_t hoursWest)
90 {
91 struct timeval currentTime;
92 struct timezone timeZone;
93 gettimeofday(¤tTime, &timeZone);
94
95 TimeOfNow timeOfNow(hoursWest);
96 int32_t minutesWest = timeZone.tz_minuteswest;
97 if (IsHoursWestValid(timeOfNow.hoursWest_)) {
98 minutesWest = Round(TOTAL_MINUTE_OF_HOUR * timeOfNow.hoursWest_);
99 } else {
100 // when [hoursWest] is invalid, set current time zone to [hoursWest].
101 // default value of hoursWest_ is INT_MAX
102 if (!NearEqual(timeOfNow.hoursWest_, INT_MAX)) {
103 LOGW("hoursWest [%{public}d] is invalid, use current time zone.", timeOfNow.hoursWest_);
104 }
105 timeOfNow.hoursWest_ = timeZone.tz_minuteswest / TOTAL_MINUTE_OF_HOUR;
106 }
107 int secondsOfToday = currentTime.tv_sec % TOTAL_SECONDS_OF_DAY - minutesWest * TOTAL_SECONDS_OF_MINUTE;
108 if (secondsOfToday < 0) {
109 secondsOfToday += TOTAL_SECONDS_OF_DAY;
110 }
111 timeOfNow.minute_ = (secondsOfToday / TOTAL_SECONDS_OF_MINUTE) % TOTAL_MINUTE_OF_HOUR +
112 secondsOfToday % TOTAL_SECONDS_OF_MINUTE / TOTAL_SECONDS_OF_MINUTE;
113 timeOfNow.hour24_ =
114 (secondsOfToday / TOTAL_SECONDS_OF_HOUR) % TWENTY_FOUR_HOUR_BASE + timeOfNow.minute_ / TOTAL_MINUTE_OF_HOUR;
115 timeOfNow.hour12_ =
116 (timeOfNow.hour24_ < TWELVE_HOUR_BASE) ? timeOfNow.hour24_ : (timeOfNow.hour24_ - TWELVE_HOUR_BASE);
117 timeOfNow.second_ = secondsOfToday % TOTAL_SECONDS_OF_MINUTE;
118 timeOfNow.timeUsec_ = currentTime.tv_usec;
119 return timeOfNow;
120 }
121
IsHoursWestValid(int32_t & hoursWest)122 bool IsHoursWestValid(int32_t& hoursWest)
123 {
124 // valid hoursWest is within [-14, 12]
125 bool isValid = GreatOrEqual(hoursWest, HOURS_WEST_LOWER_LIMIT) && LessOrEqual(hoursWest, HOURS_WEST_UPPER_LIMIT);
126 if (!isValid) {
127 return false;
128 }
129 // Theoretically, the time zone range should be [-12, +12], but some countries and regions that cross the
130 // International Date Line use -13(UTC+13) and -14(UTC+14) to keep the whole country or region at the same date.
131 bool isSpecialTimeZone = LessNotEqual(hoursWest, HOURS_WEST_GEOGRAPHICAL_LOWER_LIMIT);
132 if (isSpecialTimeZone) {
133 hoursWest += TWENTY_FOUR_HOUR_BASE;
134 }
135 return true;
136 }
137
IsDayTime(const TimeOfNow & timeOfNow)138 bool IsDayTime(const TimeOfNow& timeOfNow)
139 {
140 return GreatOrEqual(timeOfNow.hour24_, DAY_TIME_LOWER_LIMIT) &&
141 LessNotEqual(timeOfNow.hour24_, DAY_TIME_UPPER_LIMIT);
142 }
143
GetTimeOfZone(int32_t hoursWest)144 TimeOfZone GetTimeOfZone(int32_t hoursWest)
145 {
146 struct timeval currentTime;
147 struct timezone timeZone;
148 gettimeofday(¤tTime, &timeZone);
149
150 TimeOfZone timeOfZone(hoursWest);
151 int32_t minutesWest = timeZone.tz_minuteswest;
152 if (HoursWestIsValid(timeOfZone.hoursWest_)) {
153 minutesWest = Round(TOTAL_MINUTE_OF_HOUR * timeOfZone.hoursWest_);
154 } else {
155 // when [hoursWest] is invalid, set current time zone to [hoursWest].
156 // default value of hoursWest_ is DEFAULT_HOURS_WEST
157 if (!NearEqual(timeOfZone.hoursWest_, DEFAULT_HOURS_WEST)) {
158 LOGW("hoursWest [%{public}d] is invalid, use current time zone.", timeOfZone.hoursWest_);
159 }
160 timeOfZone.hoursWest_ = minutesWest / TOTAL_MINUTE_OF_HOUR;
161 }
162 int secondsOfToday = currentTime.tv_sec % TOTAL_SECONDS_OF_DAY - minutesWest * TOTAL_SECONDS_OF_MINUTE;
163 if (secondsOfToday < 0) {
164 secondsOfToday += TOTAL_SECONDS_OF_DAY;
165 }
166 timeOfZone.minute_ = (secondsOfToday / TOTAL_SECONDS_OF_MINUTE) % TOTAL_MINUTE_OF_HOUR +
167 secondsOfToday % TOTAL_SECONDS_OF_MINUTE / TOTAL_SECONDS_OF_MINUTE;
168 timeOfZone.hour24_ =
169 (secondsOfToday / TOTAL_SECONDS_OF_HOUR) % TWENTY_FOUR_HOUR_BASE + timeOfZone.minute_ / TOTAL_MINUTE_OF_HOUR;
170 timeOfZone.hour12_ =
171 (timeOfZone.hour24_ < TWELVE_HOUR_BASE) ? timeOfZone.hour24_ : (timeOfZone.hour24_ - TWELVE_HOUR_BASE);
172 timeOfZone.second_ = secondsOfToday % TOTAL_SECONDS_OF_MINUTE;
173 timeOfZone.timeUsec_ = currentTime.tv_usec;
174 return timeOfZone;
175 }
176
HoursWestIsValid(int32_t & hoursWest)177 bool HoursWestIsValid(int32_t& hoursWest)
178 {
179 // valid hoursWest is within [-14, 12]
180 bool isValid = GreatOrEqual(hoursWest, HOURS_WEST_LOWER_LIMIT) && LessOrEqual(hoursWest, HOURS_WEST_UPPER_LIMIT);
181 if (!isValid) {
182 return false;
183 }
184 // Theoretically, the time zone range should be [-12, +12], but some countries and regions that cross the
185 // International Date Line use -13(UTC+13) and -14(UTC+14) to keep the whole country or region at the same date.
186 bool isSpecialTimeZone = LessNotEqual(hoursWest, HOURS_WEST_GEOGRAPHICAL_LOWER_LIMIT);
187 if (isSpecialTimeZone) {
188 hoursWest += TWENTY_FOUR_HOUR_BASE;
189 }
190 return true;
191 }
192
IsDayTime(const TimeOfZone & timeOfZone)193 bool IsDayTime(const TimeOfZone& timeOfZone)
194 {
195 return GreatOrEqual(timeOfZone.hour24_, DAY_TIME_LOWER_LIMIT) &&
196 LessNotEqual(timeOfZone.hour24_, DAY_TIME_UPPER_LIMIT);
197 }
198
199 } // namespace OHOS::Ace
200