/src/brpc/src/butil/time/time.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 | | // Use of this source code is governed by a BSD-style license that can be |
3 | | // found in the LICENSE file. |
4 | | |
5 | | #include "butil/time/time.h" |
6 | | |
7 | | #include <limits> |
8 | | #include <ostream> |
9 | | |
10 | | #include "butil/float_util.h" |
11 | | #include "butil/lazy_instance.h" |
12 | | #include "butil/logging.h" |
13 | | |
14 | | namespace butil { |
15 | | |
16 | | // TimeDelta ------------------------------------------------------------------ |
17 | | |
18 | | // static |
19 | 0 | TimeDelta TimeDelta::Max() { |
20 | 0 | return TimeDelta(std::numeric_limits<int64_t>::max()); |
21 | 0 | } |
22 | | |
23 | 0 | int TimeDelta::InDays() const { |
24 | 0 | if (is_max()) { |
25 | | // Preserve max to prevent overflow. |
26 | 0 | return std::numeric_limits<int>::max(); |
27 | 0 | } |
28 | 0 | return static_cast<int>(delta_ / Time::kMicrosecondsPerDay); |
29 | 0 | } |
30 | | |
31 | 0 | int TimeDelta::InHours() const { |
32 | 0 | if (is_max()) { |
33 | | // Preserve max to prevent overflow. |
34 | 0 | return std::numeric_limits<int>::max(); |
35 | 0 | } |
36 | 0 | return static_cast<int>(delta_ / Time::kMicrosecondsPerHour); |
37 | 0 | } |
38 | | |
39 | 0 | int TimeDelta::InMinutes() const { |
40 | 0 | if (is_max()) { |
41 | | // Preserve max to prevent overflow. |
42 | 0 | return std::numeric_limits<int>::max(); |
43 | 0 | } |
44 | 0 | return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute); |
45 | 0 | } |
46 | | |
47 | 0 | double TimeDelta::InSecondsF() const { |
48 | 0 | if (is_max()) { |
49 | | // Preserve max to prevent overflow. |
50 | 0 | return std::numeric_limits<double>::infinity(); |
51 | 0 | } |
52 | 0 | return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond; |
53 | 0 | } |
54 | | |
55 | 0 | int64_t TimeDelta::InSeconds() const { |
56 | 0 | if (is_max()) { |
57 | | // Preserve max to prevent overflow. |
58 | 0 | return std::numeric_limits<int64_t>::max(); |
59 | 0 | } |
60 | 0 | return delta_ / Time::kMicrosecondsPerSecond; |
61 | 0 | } |
62 | | |
63 | 0 | double TimeDelta::InMillisecondsF() const { |
64 | 0 | if (is_max()) { |
65 | | // Preserve max to prevent overflow. |
66 | 0 | return std::numeric_limits<double>::infinity(); |
67 | 0 | } |
68 | 0 | return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond; |
69 | 0 | } |
70 | | |
71 | 0 | int64_t TimeDelta::InMilliseconds() const { |
72 | 0 | if (is_max()) { |
73 | | // Preserve max to prevent overflow. |
74 | 0 | return std::numeric_limits<int64_t>::max(); |
75 | 0 | } |
76 | 0 | return delta_ / Time::kMicrosecondsPerMillisecond; |
77 | 0 | } |
78 | | |
79 | 0 | int64_t TimeDelta::InMillisecondsRoundedUp() const { |
80 | 0 | if (is_max()) { |
81 | | // Preserve max to prevent overflow. |
82 | 0 | return std::numeric_limits<int64_t>::max(); |
83 | 0 | } |
84 | 0 | return (delta_ + Time::kMicrosecondsPerMillisecond - 1) / |
85 | 0 | Time::kMicrosecondsPerMillisecond; |
86 | 0 | } |
87 | | |
88 | 0 | int64_t TimeDelta::InMicroseconds() const { |
89 | 0 | if (is_max()) { |
90 | | // Preserve max to prevent overflow. |
91 | 0 | return std::numeric_limits<int64_t>::max(); |
92 | 0 | } |
93 | 0 | return delta_; |
94 | 0 | } |
95 | | |
96 | | // Time ----------------------------------------------------------------------- |
97 | | |
98 | | // static |
99 | 0 | Time Time::Max() { |
100 | 0 | return Time(std::numeric_limits<int64_t>::max()); |
101 | 0 | } |
102 | | |
103 | | // static |
104 | 0 | Time Time::FromTimeT(time_t tt) { |
105 | 0 | if (tt == 0) |
106 | 0 | return Time(); // Preserve 0 so we can tell it doesn't exist. |
107 | 0 | if (tt == std::numeric_limits<time_t>::max()) |
108 | 0 | return Max(); |
109 | 0 | return Time((tt * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset); |
110 | 0 | } |
111 | | |
112 | 0 | time_t Time::ToTimeT() const { |
113 | 0 | if (is_null()) |
114 | 0 | return 0; // Preserve 0 so we can tell it doesn't exist. |
115 | 0 | if (is_max()) { |
116 | | // Preserve max without offset to prevent overflow. |
117 | 0 | return std::numeric_limits<time_t>::max(); |
118 | 0 | } |
119 | 0 | if (std::numeric_limits<int64_t>::max() - kTimeTToMicrosecondsOffset <= us_) { |
120 | 0 | DLOG(WARNING) << "Overflow when converting butil::Time with internal " << |
121 | 0 | "value " << us_ << " to time_t."; |
122 | 0 | return std::numeric_limits<time_t>::max(); |
123 | 0 | } |
124 | 0 | return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond; |
125 | 0 | } |
126 | | |
127 | | // static |
128 | 0 | Time Time::FromDoubleT(double dt) { |
129 | 0 | if (dt == 0 || IsNaN(dt)) |
130 | 0 | return Time(); // Preserve 0 so we can tell it doesn't exist. |
131 | 0 | if (dt == std::numeric_limits<double>::infinity()) |
132 | 0 | return Max(); |
133 | 0 | return Time(static_cast<int64_t>((dt * |
134 | 0 | static_cast<double>(kMicrosecondsPerSecond)) + |
135 | 0 | kTimeTToMicrosecondsOffset)); |
136 | 0 | } |
137 | | |
138 | 0 | double Time::ToDoubleT() const { |
139 | 0 | if (is_null()) |
140 | 0 | return 0; // Preserve 0 so we can tell it doesn't exist. |
141 | 0 | if (is_max()) { |
142 | | // Preserve max without offset to prevent overflow. |
143 | 0 | return std::numeric_limits<double>::infinity(); |
144 | 0 | } |
145 | 0 | return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) / |
146 | 0 | static_cast<double>(kMicrosecondsPerSecond)); |
147 | 0 | } |
148 | | |
149 | | #if defined(OS_POSIX) |
150 | | // static |
151 | 0 | Time Time::FromTimeSpec(const timespec& ts) { |
152 | 0 | return FromDoubleT(ts.tv_sec + |
153 | 0 | static_cast<double>(ts.tv_nsec) / |
154 | 0 | butil::Time::kNanosecondsPerSecond); |
155 | 0 | } |
156 | | #endif |
157 | | |
158 | | // static |
159 | 0 | Time Time::FromJsTime(double ms_since_epoch) { |
160 | | // The epoch is a valid time, so this constructor doesn't interpret |
161 | | // 0 as the null time. |
162 | 0 | if (ms_since_epoch == std::numeric_limits<double>::infinity()) |
163 | 0 | return Max(); |
164 | 0 | return Time(static_cast<int64_t>(ms_since_epoch * kMicrosecondsPerMillisecond) + |
165 | 0 | kTimeTToMicrosecondsOffset); |
166 | 0 | } |
167 | | |
168 | 0 | double Time::ToJsTime() const { |
169 | 0 | if (is_null()) { |
170 | | // Preserve 0 so the invalid result doesn't depend on the platform. |
171 | 0 | return 0; |
172 | 0 | } |
173 | 0 | if (is_max()) { |
174 | | // Preserve max without offset to prevent overflow. |
175 | 0 | return std::numeric_limits<double>::infinity(); |
176 | 0 | } |
177 | 0 | return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) / |
178 | 0 | kMicrosecondsPerMillisecond); |
179 | 0 | } |
180 | | |
181 | 0 | int64_t Time::ToJavaTime() const { |
182 | 0 | if (is_null()) { |
183 | | // Preserve 0 so the invalid result doesn't depend on the platform. |
184 | 0 | return 0; |
185 | 0 | } |
186 | 0 | if (is_max()) { |
187 | | // Preserve max without offset to prevent overflow. |
188 | 0 | return std::numeric_limits<int64_t>::max(); |
189 | 0 | } |
190 | 0 | return ((us_ - kTimeTToMicrosecondsOffset) / |
191 | 0 | kMicrosecondsPerMillisecond); |
192 | 0 | } |
193 | | |
194 | | // static |
195 | 0 | Time Time::UnixEpoch() { |
196 | 0 | Time time; |
197 | 0 | time.us_ = kTimeTToMicrosecondsOffset; |
198 | 0 | return time; |
199 | 0 | } |
200 | | |
201 | 0 | Time Time::LocalMidnight() const { |
202 | 0 | Exploded exploded; |
203 | 0 | LocalExplode(&exploded); |
204 | 0 | exploded.hour = 0; |
205 | 0 | exploded.minute = 0; |
206 | 0 | exploded.second = 0; |
207 | 0 | exploded.millisecond = 0; |
208 | 0 | return FromLocalExploded(exploded); |
209 | 0 | } |
210 | | |
211 | | // static |
212 | | bool Time::FromStringInternal(const char* time_string, |
213 | | bool is_local, |
214 | 0 | Time* parsed_time) { |
215 | | // TODO(zhujiashun): after removing nspr, this function |
216 | | // is left unimplemented. |
217 | 0 | return false; |
218 | 0 | } |
219 | | |
220 | | // Local helper class to hold the conversion from Time to TickTime at the |
221 | | // time of the Unix epoch. |
222 | | class UnixEpochSingleton { |
223 | | public: |
224 | | UnixEpochSingleton() |
225 | 0 | : unix_epoch_(TimeTicks::Now() - (Time::Now() - Time::UnixEpoch())) {} |
226 | | |
227 | 0 | TimeTicks unix_epoch() const { return unix_epoch_; } |
228 | | |
229 | | private: |
230 | | const TimeTicks unix_epoch_; |
231 | | |
232 | | DISALLOW_COPY_AND_ASSIGN(UnixEpochSingleton); |
233 | | }; |
234 | | |
235 | | static LazyInstance<UnixEpochSingleton>::Leaky |
236 | | leaky_unix_epoch_singleton_instance = LAZY_INSTANCE_INITIALIZER; |
237 | | |
238 | | // Static |
239 | 0 | TimeTicks TimeTicks::UnixEpoch() { |
240 | 0 | return leaky_unix_epoch_singleton_instance.Get().unix_epoch(); |
241 | 0 | } |
242 | | |
243 | | // Time::Exploded ------------------------------------------------------------- |
244 | | |
245 | 0 | inline bool is_in_range(int value, int lo, int hi) { |
246 | 0 | return lo <= value && value <= hi; |
247 | 0 | } |
248 | | |
249 | 0 | bool Time::Exploded::HasValidValues() const { |
250 | 0 | return is_in_range(month, 1, 12) && |
251 | 0 | is_in_range(day_of_week, 0, 6) && |
252 | 0 | is_in_range(day_of_month, 1, 31) && |
253 | 0 | is_in_range(hour, 0, 23) && |
254 | 0 | is_in_range(minute, 0, 59) && |
255 | 0 | is_in_range(second, 0, 60) && |
256 | 0 | is_in_range(millisecond, 0, 999); |
257 | 0 | } |
258 | | |
259 | | } // namespace butil |