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 <limits>
9 #include <ostream>
10 #include <tuple>
11 #include <utility>
12
13 #include "base/no_destructor.h"
14 #include "base/optional.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/third_party/nspr/prtime.h"
18 #include "base/time/time_override.h"
19 #include "build/build_config.h"
20
21 namespace base {
22
23 namespace {
24
25 // Strips the |expected| prefix from the start of the given string, returning
26 // |true| if the strip operation succeeded or false otherwise.
27 //
28 // Example:
29 //
30 // StringPiece input("abc");
31 // EXPECT_TRUE(ConsumePrefix(input, "a"));
32 // EXPECT_EQ(input, "bc");
33 //
34 // Adapted from absl::ConsumePrefix():
35 // https://cs.chromium.org/chromium/src/third_party/abseil-cpp/absl/strings/strip.h?l=45&rcl=2c22e9135f107a4319582ae52e2e3e6b201b6b7c
ConsumePrefix(StringPiece & str,StringPiece expected)36 bool ConsumePrefix(StringPiece& str, StringPiece expected) {
37 if (!StartsWith(str, expected))
38 return false;
39 str.remove_prefix(expected.size());
40 return true;
41 }
42
43 // Utility struct used by ConsumeDurationNumber() to parse decimal numbers.
44 // A ParsedDecimal represents the number `int_part` + `frac_part`/`frac_scale`,
45 // where:
46 // (i) 0 <= `frac_part` < `frac_scale` (implies `frac_part`/`frac_scale` < 1)
47 // (ii) `frac_scale` is 10^[number of digits after the decimal point]
48 //
49 // Example:
50 // -42 => {.int_part = -42, .frac_part = 0, .frac_scale = 1}
51 // 1.23 => {.int_part = 1, .frac_part = 23, .frac_scale = 100}
52 struct ParsedDecimal {
53 int64_t int_part = 0;
54 int64_t frac_part = 0;
55 int64_t frac_scale = 1;
56 };
57
58 // A helper for FromString() that tries to parse a leading number from the given
59 // StringPiece. |number_string| is modified to start from the first unconsumed
60 // char.
61 //
62 // Adapted from absl:
63 // https://cs.chromium.org/chromium/src/third_party/abseil-cpp/absl/time/duration.cc?l=807&rcl=2c22e9135f107a4319582ae52e2e3e6b201b6b7c
ConsumeDurationNumber(StringPiece & number_string)64 constexpr Optional<ParsedDecimal> ConsumeDurationNumber(
65 StringPiece& number_string) {
66 ParsedDecimal res;
67 StringPiece::const_iterator orig_start = number_string.begin();
68 // Parse contiguous digits.
69 for (; !number_string.empty(); number_string.remove_prefix(1)) {
70 const int d = number_string.front() - '0';
71 if (d < 0 || d >= 10)
72 break;
73
74 if (res.int_part > std::numeric_limits<int64_t>::max() / 10)
75 return nullopt;
76 res.int_part *= 10;
77 if (res.int_part > std::numeric_limits<int64_t>::max() - d)
78 return nullopt;
79 res.int_part += d;
80 }
81 const bool int_part_empty = number_string.begin() == orig_start;
82 if (number_string.empty() || number_string.front() != '.')
83 return int_part_empty ? nullopt : make_optional(res);
84
85 number_string.remove_prefix(1); // consume '.'
86 // Parse contiguous digits.
87 for (; !number_string.empty(); number_string.remove_prefix(1)) {
88 const int d = number_string.front() - '0';
89 if (d < 0 || d >= 10)
90 break;
91 DCHECK_LT(res.frac_part, res.frac_scale);
92 if (res.frac_scale <= std::numeric_limits<int64_t>::max() / 10) {
93 // |frac_part| will not overflow because it is always < |frac_scale|.
94 res.frac_part *= 10;
95 res.frac_part += d;
96 res.frac_scale *= 10;
97 }
98 }
99
100 return int_part_empty && res.frac_scale == 1 ? nullopt : make_optional(res);
101 }
102
103 // A helper for FromString() that tries to parse a leading unit designator
104 // (e.g., ns, us, ms, s, m, h) from the given StringPiece. |unit_string| is
105 // modified to start from the first unconsumed char.
106 //
107 // Adapted from absl:
108 // https://cs.chromium.org/chromium/src/third_party/abseil-cpp/absl/time/duration.cc?l=841&rcl=2c22e9135f107a4319582ae52e2e3e6b201b6b7c
ConsumeDurationUnit(StringPiece & unit_string)109 Optional<TimeDelta> ConsumeDurationUnit(StringPiece& unit_string) {
110 for (const auto& str_delta : {
111 std::make_pair("ns", TimeDelta::FromNanoseconds(1)),
112 std::make_pair("us", TimeDelta::FromMicroseconds(1)),
113 // Note: "ms" MUST be checked before "m" to ensure that milliseconds
114 // are not parsed as minutes.
115 std::make_pair("ms", TimeDelta::FromMilliseconds(1)),
116 std::make_pair("s", TimeDelta::FromSeconds(1)),
117 std::make_pair("m", TimeDelta::FromMinutes(1)),
118 std::make_pair("h", TimeDelta::FromHours(1)),
119 }) {
120 if (ConsumePrefix(unit_string, str_delta.first))
121 return str_delta.second;
122 }
123
124 return nullopt;
125 }
126
127 } // namespace
128
129 namespace internal {
130
131 TimeNowFunction g_time_now_function = &subtle::TimeNowIgnoringOverride;
132
133 TimeNowFunction g_time_now_from_system_time_function =
134 &subtle::TimeNowFromSystemTimeIgnoringOverride;
135
136 TimeTicksNowFunction g_time_ticks_now_function =
137 &subtle::TimeTicksNowIgnoringOverride;
138
139 ThreadTicksNowFunction g_thread_ticks_now_function =
140 &subtle::ThreadTicksNowIgnoringOverride;
141
142 } // namespace internal
143
144 // TimeDelta ------------------------------------------------------------------
145
146 // static
FromString(StringPiece duration_string)147 Optional<TimeDelta> TimeDelta::FromString(StringPiece duration_string) {
148 int sign = 1;
149 if (ConsumePrefix(duration_string, "-"))
150 sign = -1;
151 else
152 ConsumePrefix(duration_string, "+");
153 if (duration_string.empty())
154 return nullopt;
155
156 // Handle special-case values that don't require units.
157 if (duration_string == "0")
158 return TimeDelta();
159 if (duration_string == "inf")
160 return sign == 1 ? TimeDelta::Max() : TimeDelta::Min();
161
162 TimeDelta delta;
163 while (!duration_string.empty()) {
164 Optional<ParsedDecimal> number_opt = ConsumeDurationNumber(duration_string);
165 if (!number_opt.has_value())
166 return nullopt;
167 Optional<TimeDelta> unit_opt = ConsumeDurationUnit(duration_string);
168 if (!unit_opt.has_value())
169 return nullopt;
170
171 ParsedDecimal number = number_opt.value();
172 TimeDelta unit = unit_opt.value();
173 if (number.int_part != 0)
174 delta += sign * number.int_part * unit;
175 if (number.frac_part != 0)
176 delta += (double{sign} * number.frac_part / number.frac_scale) * unit;
177 }
178 return delta;
179 }
180
InDays() const181 int TimeDelta::InDays() const {
182 if (!is_inf())
183 return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
184 return (delta_ < 0) ? std::numeric_limits<int>::min()
185 : std::numeric_limits<int>::max();
186 }
187
InDaysFloored() const188 int TimeDelta::InDaysFloored() const {
189 if (!is_inf()) {
190 const int result = delta_ / Time::kMicrosecondsPerDay;
191 // Convert |result| from truncating to flooring.
192 return (result * Time::kMicrosecondsPerDay > delta_) ? (result - 1)
193 : result;
194 }
195 return (delta_ < 0) ? std::numeric_limits<int>::min()
196 : std::numeric_limits<int>::max();
197 }
198
InSecondsF() const199 double TimeDelta::InSecondsF() const {
200 if (!is_inf())
201 return double{delta_} / Time::kMicrosecondsPerSecond;
202 return (delta_ < 0) ? -std::numeric_limits<double>::infinity()
203 : std::numeric_limits<double>::infinity();
204 }
205
InSeconds() const206 int64_t TimeDelta::InSeconds() const {
207 return is_inf() ? delta_ : (delta_ / Time::kMicrosecondsPerSecond);
208 }
209
InMillisecondsF() const210 double TimeDelta::InMillisecondsF() const {
211 if (!is_inf())
212 return double{delta_} / Time::kMicrosecondsPerMillisecond;
213 return (delta_ < 0) ? -std::numeric_limits<double>::infinity()
214 : std::numeric_limits<double>::infinity();
215 }
216
InMilliseconds() const217 int64_t TimeDelta::InMilliseconds() const {
218 if (!is_inf())
219 return delta_ / Time::kMicrosecondsPerMillisecond;
220 return (delta_ < 0) ? std::numeric_limits<int64_t>::min()
221 : std::numeric_limits<int64_t>::max();
222 }
223
InMillisecondsRoundedUp() const224 int64_t TimeDelta::InMillisecondsRoundedUp() const {
225 if (!is_inf()) {
226 const int64_t result = delta_ / Time::kMicrosecondsPerMillisecond;
227 // Convert |result| from truncating to ceiling.
228 return (delta_ > result * Time::kMicrosecondsPerMillisecond) ? (result + 1)
229 : result;
230 }
231 return delta_;
232 }
233
InMicrosecondsF() const234 double TimeDelta::InMicrosecondsF() const {
235 if (!is_inf())
236 return double{delta_};
237 return (delta_ < 0) ? -std::numeric_limits<double>::infinity()
238 : std::numeric_limits<double>::infinity();
239 }
240
CeilToMultiple(TimeDelta interval) const241 TimeDelta TimeDelta::CeilToMultiple(TimeDelta interval) const {
242 if (is_inf() || interval.is_zero())
243 return *this;
244 const TimeDelta remainder = *this % interval;
245 if (delta_ < 0)
246 return *this - remainder;
247 return remainder.is_zero() ? *this
248 : (*this - remainder + interval.magnitude());
249 }
250
FloorToMultiple(TimeDelta interval) const251 TimeDelta TimeDelta::FloorToMultiple(TimeDelta interval) const {
252 if (is_inf() || interval.is_zero())
253 return *this;
254 const TimeDelta remainder = *this % interval;
255 if (delta_ < 0) {
256 return remainder.is_zero() ? *this
257 : (*this - remainder - interval.magnitude());
258 }
259 return *this - remainder;
260 }
261
RoundToMultiple(TimeDelta interval) const262 TimeDelta TimeDelta::RoundToMultiple(TimeDelta interval) const {
263 if (is_inf() || interval.is_zero())
264 return *this;
265 if (interval.is_inf())
266 return TimeDelta();
267 const TimeDelta half = interval.magnitude() / 2;
268 return (delta_ < 0) ? (*this - half).CeilToMultiple(interval)
269 : (*this + half).FloorToMultiple(interval);
270 }
271
operator <<(std::ostream & os,TimeDelta time_delta)272 std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) {
273 return os << time_delta.InSecondsF() << " s";
274 }
275
276 // Time -----------------------------------------------------------------------
277
278 // static
Now()279 Time Time::Now() {
280 return internal::g_time_now_function();
281 }
282
283 // static
NowFromSystemTime()284 Time Time::NowFromSystemTime() {
285 // Just use g_time_now_function because it returns the system time.
286 return internal::g_time_now_from_system_time_function();
287 }
288
289 // static
FromDeltaSinceWindowsEpoch(TimeDelta delta)290 Time Time::FromDeltaSinceWindowsEpoch(TimeDelta delta) {
291 return Time(delta.InMicroseconds());
292 }
293
ToDeltaSinceWindowsEpoch() const294 TimeDelta Time::ToDeltaSinceWindowsEpoch() const {
295 return TimeDelta::FromMicroseconds(us_);
296 }
297
298 // static
FromTimeT(time_t tt)299 Time Time::FromTimeT(time_t tt) {
300 if (tt == 0)
301 return Time(); // Preserve 0 so we can tell it doesn't exist.
302 return (tt == std::numeric_limits<time_t>::max())
303 ? Max()
304 : (UnixEpoch() + TimeDelta::FromSeconds(tt));
305 }
306
ToTimeT() const307 time_t Time::ToTimeT() const {
308 if (is_null())
309 return 0; // Preserve 0 so we can tell it doesn't exist.
310 if (!is_inf() && ((std::numeric_limits<int64_t>::max() -
311 kTimeTToMicrosecondsOffset) > us_))
312 return (*this - UnixEpoch()).InSeconds();
313 return (us_ < 0) ? std::numeric_limits<time_t>::min()
314 : std::numeric_limits<time_t>::max();
315 }
316
317 // static
FromDoubleT(double dt)318 Time Time::FromDoubleT(double dt) {
319 // Preserve 0 so we can tell it doesn't exist.
320 return (dt == 0 || std::isnan(dt))
321 ? Time()
322 : (UnixEpoch() + TimeDelta::FromSecondsD(dt));
323 }
324
ToDoubleT() const325 double Time::ToDoubleT() const {
326 if (is_null())
327 return 0; // Preserve 0 so we can tell it doesn't exist.
328 if (!is_inf())
329 return (*this - UnixEpoch()).InSecondsF();
330 return (us_ < 0) ? -std::numeric_limits<double>::infinity()
331 : std::numeric_limits<double>::infinity();
332 }
333
334 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
335 // static
FromTimeSpec(const timespec & ts)336 Time Time::FromTimeSpec(const timespec& ts) {
337 return FromDoubleT(ts.tv_sec + double{ts.tv_nsec} / kNanosecondsPerSecond);
338 }
339 #endif
340
341 // static
FromJsTime(double ms_since_epoch)342 Time Time::FromJsTime(double ms_since_epoch) {
343 // The epoch is a valid time, so this constructor doesn't interpret 0 as the
344 // null time.
345 return UnixEpoch() + TimeDelta::FromMillisecondsD(ms_since_epoch);
346 }
347
ToJsTime() const348 double Time::ToJsTime() const {
349 // Preserve 0 so the invalid result doesn't depend on the platform.
350 return is_null() ? 0 : ToJsTimeIgnoringNull();
351 }
352
ToJsTimeIgnoringNull() const353 double Time::ToJsTimeIgnoringNull() const {
354 // Preserve max and min without offset to prevent over/underflow.
355 if (!is_inf())
356 return (*this - UnixEpoch()).InMillisecondsF();
357 return (us_ < 0) ? -std::numeric_limits<double>::infinity()
358 : std::numeric_limits<double>::infinity();
359 }
360
FromJavaTime(int64_t ms_since_epoch)361 Time Time::FromJavaTime(int64_t ms_since_epoch) {
362 return UnixEpoch() + TimeDelta::FromMilliseconds(ms_since_epoch);
363 }
364
ToJavaTime() const365 int64_t Time::ToJavaTime() const {
366 // Preserve 0 so the invalid result doesn't depend on the platform.
367 if (is_null())
368 return 0;
369 if (!is_inf())
370 return (*this - UnixEpoch()).InMilliseconds();
371 return (us_ < 0) ? std::numeric_limits<int64_t>::min()
372 : std::numeric_limits<int64_t>::max();
373 }
374
375 // static
UnixEpoch()376 Time Time::UnixEpoch() {
377 return Time(kTimeTToMicrosecondsOffset);
378 }
379
Midnight(bool is_local) const380 Time Time::Midnight(bool is_local) const {
381 Exploded exploded;
382 Explode(is_local, &exploded);
383 exploded.hour = 0;
384 exploded.minute = 0;
385 exploded.second = 0;
386 exploded.millisecond = 0;
387 Time out_time;
388 if (FromExploded(is_local, exploded, &out_time))
389 return out_time;
390
391 // Reaching here means 00:00:00am of the current day does not exist (due to
392 // Daylight Saving Time in some countries where clocks are shifted at
393 // midnight). In this case, midnight should be defined as 01:00:00am.
394 DCHECK(is_local);
395 exploded.hour = 1;
396 const bool result = FromExploded(is_local, exploded, &out_time);
397 DCHECK(result); // This function must not fail.
398 return out_time;
399 }
400
401 // static
FromStringInternal(const char * time_string,bool is_local,Time * parsed_time)402 bool Time::FromStringInternal(const char* time_string,
403 bool is_local,
404 Time* parsed_time) {
405 DCHECK(time_string);
406 DCHECK(parsed_time);
407
408 if (time_string[0] == '\0')
409 return false;
410
411 PRTime result_time = 0;
412 PRStatus result = PR_ParseTimeString(time_string,
413 is_local ? PR_FALSE : PR_TRUE,
414 &result_time);
415 if (result != PR_SUCCESS)
416 return false;
417
418 *parsed_time = UnixEpoch() + TimeDelta::FromMicroseconds(result_time);
419 return true;
420 }
421
422 // static
ExplodedMostlyEquals(const Exploded & lhs,const Exploded & rhs)423 bool Time::ExplodedMostlyEquals(const Exploded& lhs, const Exploded& rhs) {
424 return std::tie(lhs.year, lhs.month, lhs.day_of_month, lhs.hour, lhs.minute,
425 lhs.second, lhs.millisecond) ==
426 std::tie(rhs.year, rhs.month, rhs.day_of_month, rhs.hour, rhs.minute,
427 rhs.second, rhs.millisecond);
428 }
429
430 // static
FromMillisecondsSinceUnixEpoch(int64_t unix_milliseconds,Time * time)431 bool Time::FromMillisecondsSinceUnixEpoch(int64_t unix_milliseconds,
432 Time* time) {
433 // Adjust the provided time from milliseconds since the Unix epoch (1970) to
434 // microseconds since the Windows epoch (1601), avoiding overflows.
435 CheckedNumeric<int64_t> checked_microseconds_win_epoch = unix_milliseconds;
436 checked_microseconds_win_epoch *= kMicrosecondsPerMillisecond;
437 checked_microseconds_win_epoch += kTimeTToMicrosecondsOffset;
438 *time = Time(checked_microseconds_win_epoch.ValueOrDefault(0));
439 return checked_microseconds_win_epoch.IsValid();
440 }
441
ToRoundedDownMillisecondsSinceUnixEpoch() const442 int64_t Time::ToRoundedDownMillisecondsSinceUnixEpoch() const {
443 constexpr int64_t kEpochOffsetMillis =
444 kTimeTToMicrosecondsOffset / kMicrosecondsPerMillisecond;
445 static_assert(kTimeTToMicrosecondsOffset % kMicrosecondsPerMillisecond == 0,
446 "assumption: no epoch offset sub-milliseconds");
447
448 // Compute the milliseconds since UNIX epoch without the possibility of
449 // under/overflow. Round the result towards -infinity.
450 //
451 // If |us_| is negative and includes fractions of a millisecond, subtract one
452 // more to effect the round towards -infinity. C-style integer truncation
453 // takes care of all other cases.
454 const int64_t millis = us_ / kMicrosecondsPerMillisecond;
455 const int64_t submillis = us_ % kMicrosecondsPerMillisecond;
456 return millis - kEpochOffsetMillis - (submillis < 0);
457 }
458
operator <<(std::ostream & os,Time time)459 std::ostream& operator<<(std::ostream& os, Time time) {
460 Time::Exploded exploded;
461 time.UTCExplode(&exploded);
462 // Use StringPrintf because iostreams formatting is painful.
463 return os << StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d UTC",
464 exploded.year,
465 exploded.month,
466 exploded.day_of_month,
467 exploded.hour,
468 exploded.minute,
469 exploded.second,
470 exploded.millisecond);
471 }
472
473 // TimeTicks ------------------------------------------------------------------
474
475 // static
Now()476 TimeTicks TimeTicks::Now() {
477 return internal::g_time_ticks_now_function();
478 }
479
480 // static
UnixEpoch()481 TimeTicks TimeTicks::UnixEpoch() {
482 static const NoDestructor<TimeTicks> epoch([]() {
483 return subtle::TimeTicksNowIgnoringOverride() -
484 (subtle::TimeNowIgnoringOverride() - Time::UnixEpoch());
485 }());
486 return *epoch;
487 }
488
SnappedToNextTick(TimeTicks tick_phase,TimeDelta tick_interval) const489 TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase,
490 TimeDelta tick_interval) const {
491 // |interval_offset| is the offset from |this| to the next multiple of
492 // |tick_interval| after |tick_phase|, possibly negative if in the past.
493 TimeDelta interval_offset = (tick_phase - *this) % tick_interval;
494 // If |this| is exactly on the interval (i.e. offset==0), don't adjust.
495 // Otherwise, if |tick_phase| was in the past, adjust forward to the next
496 // tick after |this|.
497 if (!interval_offset.is_zero() && tick_phase < *this)
498 interval_offset += tick_interval;
499 return *this + interval_offset;
500 }
501
operator <<(std::ostream & os,TimeTicks time_ticks)502 std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
503 // This function formats a TimeTicks object as "bogo-microseconds".
504 // The origin and granularity of the count are platform-specific, and may very
505 // from run to run. Although bogo-microseconds usually roughly correspond to
506 // real microseconds, the only real guarantee is that the number never goes
507 // down during a single run.
508 const TimeDelta as_time_delta = time_ticks - TimeTicks();
509 return os << as_time_delta.InMicroseconds() << " bogo-microseconds";
510 }
511
512 // ThreadTicks ----------------------------------------------------------------
513
514 // static
Now()515 ThreadTicks ThreadTicks::Now() {
516 return internal::g_thread_ticks_now_function();
517 }
518
operator <<(std::ostream & os,ThreadTicks thread_ticks)519 std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) {
520 const TimeDelta as_time_delta = thread_ticks - ThreadTicks();
521 return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds";
522 }
523
524 // Time::Exploded -------------------------------------------------------------
525
HasValidValues() const526 bool Time::Exploded::HasValidValues() const {
527 // clang-format off
528 return (1 <= month) && (month <= 12) &&
529 (0 <= day_of_week) && (day_of_week <= 6) &&
530 (1 <= day_of_month) && (day_of_month <= 31) &&
531 (0 <= hour) && (hour <= 23) &&
532 (0 <= minute) && (minute <= 59) &&
533 (0 <= second) && (second <= 60) &&
534 (0 <= millisecond) && (millisecond <= 999);
535 // clang-format on
536 }
537
538 } // namespace base
539