/src/mozilla-central/security/sandbox/chromium/base/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 "base/time/time.h" |
6 | | |
7 | | #include <cmath> |
8 | | #include <ios> |
9 | | #include <limits> |
10 | | #include <ostream> |
11 | | #include <sstream> |
12 | | |
13 | | #include "base/lazy_instance.h" |
14 | | #include "base/logging.h" |
15 | | #include "base/macros.h" |
16 | | #include "base/strings/stringprintf.h" |
17 | | #include "base/third_party/nspr/prtime.h" |
18 | | #include "build/build_config.h" |
19 | | |
20 | | namespace base { |
21 | | |
22 | | // TimeDelta ------------------------------------------------------------------ |
23 | | |
24 | 0 | int TimeDelta::InDays() const { |
25 | 0 | if (is_max()) { |
26 | 0 | // Preserve max to prevent overflow. |
27 | 0 | return std::numeric_limits<int>::max(); |
28 | 0 | } |
29 | 0 | return static_cast<int>(delta_ / Time::kMicrosecondsPerDay); |
30 | 0 | } |
31 | | |
32 | 0 | int TimeDelta::InHours() const { |
33 | 0 | if (is_max()) { |
34 | 0 | // Preserve max to prevent overflow. |
35 | 0 | return std::numeric_limits<int>::max(); |
36 | 0 | } |
37 | 0 | return static_cast<int>(delta_ / Time::kMicrosecondsPerHour); |
38 | 0 | } |
39 | | |
40 | 0 | int TimeDelta::InMinutes() const { |
41 | 0 | if (is_max()) { |
42 | 0 | // Preserve max to prevent overflow. |
43 | 0 | return std::numeric_limits<int>::max(); |
44 | 0 | } |
45 | 0 | return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute); |
46 | 0 | } |
47 | | |
48 | 0 | double TimeDelta::InSecondsF() const { |
49 | 0 | if (is_max()) { |
50 | 0 | // Preserve max to prevent overflow. |
51 | 0 | return std::numeric_limits<double>::infinity(); |
52 | 0 | } |
53 | 0 | return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond; |
54 | 0 | } |
55 | | |
56 | 0 | int64_t TimeDelta::InSeconds() const { |
57 | 0 | if (is_max()) { |
58 | 0 | // Preserve max to prevent overflow. |
59 | 0 | return std::numeric_limits<int64_t>::max(); |
60 | 0 | } |
61 | 0 | return delta_ / Time::kMicrosecondsPerSecond; |
62 | 0 | } |
63 | | |
64 | 0 | double TimeDelta::InMillisecondsF() const { |
65 | 0 | if (is_max()) { |
66 | 0 | // Preserve max to prevent overflow. |
67 | 0 | return std::numeric_limits<double>::infinity(); |
68 | 0 | } |
69 | 0 | return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond; |
70 | 0 | } |
71 | | |
72 | 0 | int64_t TimeDelta::InMilliseconds() const { |
73 | 0 | if (is_max()) { |
74 | 0 | // Preserve max to prevent overflow. |
75 | 0 | return std::numeric_limits<int64_t>::max(); |
76 | 0 | } |
77 | 0 | return delta_ / Time::kMicrosecondsPerMillisecond; |
78 | 0 | } |
79 | | |
80 | 0 | int64_t TimeDelta::InMillisecondsRoundedUp() const { |
81 | 0 | if (is_max()) { |
82 | 0 | // Preserve max to prevent overflow. |
83 | 0 | return std::numeric_limits<int64_t>::max(); |
84 | 0 | } |
85 | 0 | return (delta_ + Time::kMicrosecondsPerMillisecond - 1) / |
86 | 0 | Time::kMicrosecondsPerMillisecond; |
87 | 0 | } |
88 | | |
89 | 0 | int64_t TimeDelta::InMicroseconds() const { |
90 | 0 | if (is_max()) { |
91 | 0 | // Preserve max to prevent overflow. |
92 | 0 | return std::numeric_limits<int64_t>::max(); |
93 | 0 | } |
94 | 0 | return delta_; |
95 | 0 | } |
96 | | |
97 | 0 | int64_t TimeDelta::InNanoseconds() const { |
98 | 0 | if (is_max()) { |
99 | 0 | // Preserve max to prevent overflow. |
100 | 0 | return std::numeric_limits<int64_t>::max(); |
101 | 0 | } |
102 | 0 | return delta_ * Time::kNanosecondsPerMicrosecond; |
103 | 0 | } |
104 | | |
105 | | namespace time_internal { |
106 | | |
107 | 0 | int64_t SaturatedAdd(TimeDelta delta, int64_t value) { |
108 | 0 | CheckedNumeric<int64_t> rv(delta.delta_); |
109 | 0 | rv += value; |
110 | 0 | if (rv.IsValid()) |
111 | 0 | return rv.ValueOrDie(); |
112 | 0 | // Positive RHS overflows. Negative RHS underflows. |
113 | 0 | if (value < 0) |
114 | 0 | return std::numeric_limits<int64_t>::min(); |
115 | 0 | return std::numeric_limits<int64_t>::max(); |
116 | 0 | } |
117 | | |
118 | 0 | int64_t SaturatedSub(TimeDelta delta, int64_t value) { |
119 | 0 | CheckedNumeric<int64_t> rv(delta.delta_); |
120 | 0 | rv -= value; |
121 | 0 | if (rv.IsValid()) |
122 | 0 | return rv.ValueOrDie(); |
123 | 0 | // Negative RHS overflows. Positive RHS underflows. |
124 | 0 | if (value < 0) |
125 | 0 | return std::numeric_limits<int64_t>::max(); |
126 | 0 | return std::numeric_limits<int64_t>::min(); |
127 | 0 | } |
128 | | |
129 | | } // namespace time_internal |
130 | | |
131 | 0 | std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) { |
132 | 0 | return os << time_delta.InSecondsF() << " s"; |
133 | 0 | } |
134 | | |
135 | | // Time ----------------------------------------------------------------------- |
136 | | |
137 | | // static |
138 | 0 | Time Time::FromTimeT(time_t tt) { |
139 | 0 | if (tt == 0) |
140 | 0 | return Time(); // Preserve 0 so we can tell it doesn't exist. |
141 | 0 | if (tt == std::numeric_limits<time_t>::max()) |
142 | 0 | return Max(); |
143 | 0 | return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSeconds(tt); |
144 | 0 | } |
145 | | |
146 | 0 | time_t Time::ToTimeT() const { |
147 | 0 | if (is_null()) |
148 | 0 | return 0; // Preserve 0 so we can tell it doesn't exist. |
149 | 0 | if (is_max()) { |
150 | 0 | // Preserve max without offset to prevent overflow. |
151 | 0 | return std::numeric_limits<time_t>::max(); |
152 | 0 | } |
153 | 0 | if (std::numeric_limits<int64_t>::max() - kTimeTToMicrosecondsOffset <= us_) { |
154 | 0 | DLOG(WARNING) << "Overflow when converting base::Time with internal " << |
155 | 0 | "value " << us_ << " to time_t."; |
156 | 0 | return std::numeric_limits<time_t>::max(); |
157 | 0 | } |
158 | 0 | return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond; |
159 | 0 | } |
160 | | |
161 | | // static |
162 | 0 | Time Time::FromDoubleT(double dt) { |
163 | 0 | if (dt == 0 || std::isnan(dt)) |
164 | 0 | return Time(); // Preserve 0 so we can tell it doesn't exist. |
165 | 0 | return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSecondsD(dt); |
166 | 0 | } |
167 | | |
168 | 0 | double Time::ToDoubleT() const { |
169 | 0 | if (is_null()) |
170 | 0 | return 0; // Preserve 0 so we can tell it doesn't exist. |
171 | 0 | if (is_max()) { |
172 | 0 | // Preserve max without offset to prevent overflow. |
173 | 0 | return std::numeric_limits<double>::infinity(); |
174 | 0 | } |
175 | 0 | return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) / |
176 | 0 | static_cast<double>(kMicrosecondsPerSecond)); |
177 | 0 | } |
178 | | |
179 | | #if defined(OS_POSIX) |
180 | | // static |
181 | 0 | Time Time::FromTimeSpec(const timespec& ts) { |
182 | 0 | return FromDoubleT(ts.tv_sec + |
183 | 0 | static_cast<double>(ts.tv_nsec) / |
184 | 0 | base::Time::kNanosecondsPerSecond); |
185 | 0 | } |
186 | | #endif |
187 | | |
188 | | // static |
189 | 0 | Time Time::FromJsTime(double ms_since_epoch) { |
190 | 0 | // The epoch is a valid time, so this constructor doesn't interpret |
191 | 0 | // 0 as the null time. |
192 | 0 | return Time(kTimeTToMicrosecondsOffset) + |
193 | 0 | TimeDelta::FromMillisecondsD(ms_since_epoch); |
194 | 0 | } |
195 | | |
196 | 0 | double Time::ToJsTime() const { |
197 | 0 | if (is_null()) { |
198 | 0 | // Preserve 0 so the invalid result doesn't depend on the platform. |
199 | 0 | return 0; |
200 | 0 | } |
201 | 0 | if (is_max()) { |
202 | 0 | // Preserve max without offset to prevent overflow. |
203 | 0 | return std::numeric_limits<double>::infinity(); |
204 | 0 | } |
205 | 0 | return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) / |
206 | 0 | kMicrosecondsPerMillisecond); |
207 | 0 | } |
208 | | |
209 | 0 | Time Time::FromJavaTime(int64_t ms_since_epoch) { |
210 | 0 | return base::Time::UnixEpoch() + |
211 | 0 | base::TimeDelta::FromMilliseconds(ms_since_epoch); |
212 | 0 | } |
213 | | |
214 | 0 | int64_t Time::ToJavaTime() const { |
215 | 0 | if (is_null()) { |
216 | 0 | // Preserve 0 so the invalid result doesn't depend on the platform. |
217 | 0 | return 0; |
218 | 0 | } |
219 | 0 | if (is_max()) { |
220 | 0 | // Preserve max without offset to prevent overflow. |
221 | 0 | return std::numeric_limits<int64_t>::max(); |
222 | 0 | } |
223 | 0 | return ((us_ - kTimeTToMicrosecondsOffset) / |
224 | 0 | kMicrosecondsPerMillisecond); |
225 | 0 | } |
226 | | |
227 | | // static |
228 | 0 | Time Time::UnixEpoch() { |
229 | 0 | Time time; |
230 | 0 | time.us_ = kTimeTToMicrosecondsOffset; |
231 | 0 | return time; |
232 | 0 | } |
233 | | |
234 | 0 | Time Time::LocalMidnight() const { |
235 | 0 | Exploded exploded; |
236 | 0 | LocalExplode(&exploded); |
237 | 0 | exploded.hour = 0; |
238 | 0 | exploded.minute = 0; |
239 | 0 | exploded.second = 0; |
240 | 0 | exploded.millisecond = 0; |
241 | 0 | Time out_time; |
242 | 0 | if (FromLocalExploded(exploded, &out_time)) |
243 | 0 | return out_time; |
244 | 0 | // This function must not fail. |
245 | 0 | NOTREACHED(); |
246 | 0 | return Time(); |
247 | 0 | } |
248 | | |
249 | | #if !defined(MOZ_SANDBOX) |
250 | | // static |
251 | | bool Time::FromStringInternal(const char* time_string, |
252 | | bool is_local, |
253 | | Time* parsed_time) { |
254 | | DCHECK((time_string != NULL) && (parsed_time != NULL)); |
255 | | |
256 | | if (time_string[0] == '\0') |
257 | | return false; |
258 | | |
259 | | PRTime result_time = 0; |
260 | | PRStatus result = PR_ParseTimeString(time_string, |
261 | | is_local ? PR_FALSE : PR_TRUE, |
262 | | &result_time); |
263 | | if (PR_SUCCESS != result) |
264 | | return false; |
265 | | |
266 | | result_time += kTimeTToMicrosecondsOffset; |
267 | | *parsed_time = Time(result_time); |
268 | | return true; |
269 | | } |
270 | | #endif |
271 | | |
272 | | // static |
273 | 0 | bool Time::ExplodedMostlyEquals(const Exploded& lhs, const Exploded& rhs) { |
274 | 0 | return lhs.year == rhs.year && lhs.month == rhs.month && |
275 | 0 | lhs.day_of_month == rhs.day_of_month && lhs.hour == rhs.hour && |
276 | 0 | lhs.minute == rhs.minute && lhs.second == rhs.second && |
277 | 0 | lhs.millisecond == rhs.millisecond; |
278 | 0 | } |
279 | | |
280 | 0 | std::ostream& operator<<(std::ostream& os, Time time) { |
281 | 0 | Time::Exploded exploded; |
282 | 0 | time.UTCExplode(&exploded); |
283 | 0 | // Use StringPrintf because iostreams formatting is painful. |
284 | 0 | return os << StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d UTC", |
285 | 0 | exploded.year, |
286 | 0 | exploded.month, |
287 | 0 | exploded.day_of_month, |
288 | 0 | exploded.hour, |
289 | 0 | exploded.minute, |
290 | 0 | exploded.second, |
291 | 0 | exploded.millisecond); |
292 | 0 | } |
293 | | |
294 | | // Local helper class to hold the conversion from Time to TickTime at the |
295 | | // time of the Unix epoch. |
296 | | class UnixEpochSingleton { |
297 | | public: |
298 | | UnixEpochSingleton() |
299 | 0 | : unix_epoch_(TimeTicks::Now() - (Time::Now() - Time::UnixEpoch())) {} |
300 | | |
301 | 0 | TimeTicks unix_epoch() const { return unix_epoch_; } |
302 | | |
303 | | private: |
304 | | const TimeTicks unix_epoch_; |
305 | | |
306 | | DISALLOW_COPY_AND_ASSIGN(UnixEpochSingleton); |
307 | | }; |
308 | | |
309 | | static LazyInstance<UnixEpochSingleton>::Leaky |
310 | | leaky_unix_epoch_singleton_instance = LAZY_INSTANCE_INITIALIZER; |
311 | | |
312 | | // Static |
313 | 0 | TimeTicks TimeTicks::UnixEpoch() { |
314 | 0 | return leaky_unix_epoch_singleton_instance.Get().unix_epoch(); |
315 | 0 | } |
316 | | |
317 | | TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase, |
318 | 0 | TimeDelta tick_interval) const { |
319 | 0 | // |interval_offset| is the offset from |this| to the next multiple of |
320 | 0 | // |tick_interval| after |tick_phase|, possibly negative if in the past. |
321 | 0 | TimeDelta interval_offset = (tick_phase - *this) % tick_interval; |
322 | 0 | // If |this| is exactly on the interval (i.e. offset==0), don't adjust. |
323 | 0 | // Otherwise, if |tick_phase| was in the past, adjust forward to the next |
324 | 0 | // tick after |this|. |
325 | 0 | if (!interval_offset.is_zero() && tick_phase < *this) |
326 | 0 | interval_offset += tick_interval; |
327 | 0 | return *this + interval_offset; |
328 | 0 | } |
329 | | |
330 | 0 | std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) { |
331 | 0 | // This function formats a TimeTicks object as "bogo-microseconds". |
332 | 0 | // The origin and granularity of the count are platform-specific, and may very |
333 | 0 | // from run to run. Although bogo-microseconds usually roughly correspond to |
334 | 0 | // real microseconds, the only real guarantee is that the number never goes |
335 | 0 | // down during a single run. |
336 | 0 | const TimeDelta as_time_delta = time_ticks - TimeTicks(); |
337 | 0 | return os << as_time_delta.InMicroseconds() << " bogo-microseconds"; |
338 | 0 | } |
339 | | |
340 | 0 | std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) { |
341 | 0 | const TimeDelta as_time_delta = thread_ticks - ThreadTicks(); |
342 | 0 | return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds"; |
343 | 0 | } |
344 | | |
345 | | // Time::Exploded ------------------------------------------------------------- |
346 | | |
347 | 0 | inline bool is_in_range(int value, int lo, int hi) { |
348 | 0 | return lo <= value && value <= hi; |
349 | 0 | } |
350 | | |
351 | 0 | bool Time::Exploded::HasValidValues() const { |
352 | 0 | return is_in_range(month, 1, 12) && |
353 | 0 | is_in_range(day_of_week, 0, 6) && |
354 | 0 | is_in_range(day_of_month, 1, 31) && |
355 | 0 | is_in_range(hour, 0, 23) && |
356 | 0 | is_in_range(minute, 0, 59) && |
357 | 0 | is_in_range(second, 0, 60) && |
358 | 0 | is_in_range(millisecond, 0, 999); |
359 | 0 | } |
360 | | |
361 | | } // namespace base |