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