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/logging.h"
14 #include "base/macros.h"
15 #include "base/no_destructor.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 internal {
24 
25 TimeNowFunction g_time_now_function = &subtle::TimeNowIgnoringOverride;
26 
27 TimeNowFunction g_time_now_from_system_time_function =
28     &subtle::TimeNowFromSystemTimeIgnoringOverride;
29 
30 TimeTicksNowFunction g_time_ticks_now_function =
31     &subtle::TimeTicksNowIgnoringOverride;
32 
33 ThreadTicksNowFunction g_thread_ticks_now_function =
34     &subtle::ThreadTicksNowIgnoringOverride;
35 
36 }  // namespace internal
37 
38 // TimeDelta ------------------------------------------------------------------
39 
InDays() const40 int TimeDelta::InDays() const {
41   if (is_max()) {
42     // Preserve max to prevent overflow.
43     return std::numeric_limits<int>::max();
44   }
45   return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
46 }
47 
InDaysFloored() const48 int TimeDelta::InDaysFloored() const {
49   if (is_max()) {
50     // Preserve max to prevent overflow.
51     return std::numeric_limits<int>::max();
52   }
53   int result = delta_ / Time::kMicrosecondsPerDay;
54   int64_t remainder = delta_ - (result * Time::kMicrosecondsPerDay);
55   if (remainder < 0) {
56     --result;  // Use floor(), not trunc() rounding behavior.
57   }
58   return result;
59 }
60 
InHours() const61 int TimeDelta::InHours() const {
62   if (is_max()) {
63     // Preserve max to prevent overflow.
64     return std::numeric_limits<int>::max();
65   }
66   return static_cast<int>(delta_ / Time::kMicrosecondsPerHour);
67 }
68 
InMinutes() const69 int TimeDelta::InMinutes() const {
70   if (is_max()) {
71     // Preserve max to prevent overflow.
72     return std::numeric_limits<int>::max();
73   }
74   return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute);
75 }
76 
InSecondsF() const77 double TimeDelta::InSecondsF() const {
78   if (is_max()) {
79     // Preserve max to prevent overflow.
80     return std::numeric_limits<double>::infinity();
81   }
82   return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond;
83 }
84 
InSeconds() const85 int64_t TimeDelta::InSeconds() const {
86   if (is_max()) {
87     // Preserve max to prevent overflow.
88     return std::numeric_limits<int64_t>::max();
89   }
90   return delta_ / Time::kMicrosecondsPerSecond;
91 }
92 
InMillisecondsF() const93 double TimeDelta::InMillisecondsF() const {
94   if (is_max()) {
95     // Preserve max to prevent overflow.
96     return std::numeric_limits<double>::infinity();
97   }
98   return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond;
99 }
100 
InMilliseconds() const101 int64_t TimeDelta::InMilliseconds() const {
102   if (is_max()) {
103     // Preserve max to prevent overflow.
104     return std::numeric_limits<int64_t>::max();
105   }
106   return delta_ / Time::kMicrosecondsPerMillisecond;
107 }
108 
InMillisecondsRoundedUp() const109 int64_t TimeDelta::InMillisecondsRoundedUp() const {
110   if (is_max()) {
111     // Preserve max to prevent overflow.
112     return std::numeric_limits<int64_t>::max();
113   }
114   int64_t result = delta_ / Time::kMicrosecondsPerMillisecond;
115   int64_t remainder = delta_ - (result * Time::kMicrosecondsPerMillisecond);
116   if (remainder > 0) {
117     ++result;  // Use ceil(), not trunc() rounding behavior.
118   }
119   return result;
120 }
121 
InMicrosecondsF() const122 double TimeDelta::InMicrosecondsF() const {
123   if (is_max()) {
124     // Preserve max to prevent overflow.
125     return std::numeric_limits<double>::infinity();
126   }
127   return static_cast<double>(delta_);
128 }
129 
InNanoseconds() const130 int64_t TimeDelta::InNanoseconds() const {
131   if (is_max()) {
132     // Preserve max to prevent overflow.
133     return std::numeric_limits<int64_t>::max();
134   }
135   return delta_ * Time::kNanosecondsPerMicrosecond;
136 }
137 
operator <<(std::ostream & os,TimeDelta time_delta)138 std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) {
139   return os << time_delta.InSecondsF() << " s";
140 }
141 
142 // Time -----------------------------------------------------------------------
143 
144 // static
Now()145 Time Time::Now() {
146   return internal::g_time_now_function();
147 }
148 
149 // static
NowFromSystemTime()150 Time Time::NowFromSystemTime() {
151   // Just use g_time_now_function because it returns the system time.
152   return internal::g_time_now_from_system_time_function();
153 }
154 
155 // static
FromDeltaSinceWindowsEpoch(TimeDelta delta)156 Time Time::FromDeltaSinceWindowsEpoch(TimeDelta delta) {
157   return Time(delta.InMicroseconds());
158 }
159 
ToDeltaSinceWindowsEpoch() const160 TimeDelta Time::ToDeltaSinceWindowsEpoch() const {
161   return TimeDelta::FromMicroseconds(us_);
162 }
163 
164 // static
FromTimeT(time_t tt)165 Time Time::FromTimeT(time_t tt) {
166   if (tt == 0)
167     return Time();  // Preserve 0 so we can tell it doesn't exist.
168   if (tt == std::numeric_limits<time_t>::max())
169     return Max();
170   return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSeconds(tt);
171 }
172 
ToTimeT() const173 time_t Time::ToTimeT() const {
174   if (is_null())
175     return 0;  // Preserve 0 so we can tell it doesn't exist.
176   if (is_max()) {
177     // Preserve max without offset to prevent overflow.
178     return std::numeric_limits<time_t>::max();
179   }
180   if (std::numeric_limits<int64_t>::max() - kTimeTToMicrosecondsOffset <= us_) {
181     DLOG(WARNING) << "Overflow when converting base::Time with internal " <<
182                      "value " << us_ << " to time_t.";
183     return std::numeric_limits<time_t>::max();
184   }
185   return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond;
186 }
187 
188 // static
FromDoubleT(double dt)189 Time Time::FromDoubleT(double dt) {
190   if (dt == 0 || std::isnan(dt))
191     return Time();  // Preserve 0 so we can tell it doesn't exist.
192   return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSecondsD(dt);
193 }
194 
ToDoubleT() const195 double Time::ToDoubleT() const {
196   if (is_null())
197     return 0;  // Preserve 0 so we can tell it doesn't exist.
198   if (is_max()) {
199     // Preserve max without offset to prevent overflow.
200     return std::numeric_limits<double>::infinity();
201   }
202   return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
203           static_cast<double>(kMicrosecondsPerSecond));
204 }
205 
206 #if defined(OS_POSIX)
207 // static
FromTimeSpec(const timespec & ts)208 Time Time::FromTimeSpec(const timespec& ts) {
209   return FromDoubleT(ts.tv_sec +
210                      static_cast<double>(ts.tv_nsec) /
211                          base::Time::kNanosecondsPerSecond);
212 }
213 #endif
214 
215 // static
FromJsTime(double ms_since_epoch)216 Time Time::FromJsTime(double ms_since_epoch) {
217   // The epoch is a valid time, so this constructor doesn't interpret
218   // 0 as the null time.
219   return Time(kTimeTToMicrosecondsOffset) +
220          TimeDelta::FromMillisecondsD(ms_since_epoch);
221 }
222 
ToJsTime() const223 double Time::ToJsTime() const {
224   if (is_null()) {
225     // Preserve 0 so the invalid result doesn't depend on the platform.
226     return 0;
227   }
228   return ToJsTimeIgnoringNull();
229 }
230 
ToJsTimeIgnoringNull() const231 double Time::ToJsTimeIgnoringNull() const {
232   if (is_max()) {
233     // Preserve max without offset to prevent overflow.
234     return std::numeric_limits<double>::infinity();
235   }
236   return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
237           kMicrosecondsPerMillisecond);
238 }
239 
FromJavaTime(int64_t ms_since_epoch)240 Time Time::FromJavaTime(int64_t ms_since_epoch) {
241   return base::Time::UnixEpoch() +
242          base::TimeDelta::FromMilliseconds(ms_since_epoch);
243 }
244 
ToJavaTime() const245 int64_t Time::ToJavaTime() const {
246   if (is_null()) {
247     // Preserve 0 so the invalid result doesn't depend on the platform.
248     return 0;
249   }
250   if (is_max()) {
251     // Preserve max without offset to prevent overflow.
252     return std::numeric_limits<int64_t>::max();
253   }
254   return ((us_ - kTimeTToMicrosecondsOffset) /
255           kMicrosecondsPerMillisecond);
256 }
257 
258 // static
UnixEpoch()259 Time Time::UnixEpoch() {
260   Time time;
261   time.us_ = kTimeTToMicrosecondsOffset;
262   return time;
263 }
264 
Midnight(bool is_local) const265 Time Time::Midnight(bool is_local) const {
266   Exploded exploded;
267   Explode(is_local, &exploded);
268   exploded.hour = 0;
269   exploded.minute = 0;
270   exploded.second = 0;
271   exploded.millisecond = 0;
272   Time out_time;
273   if (FromExploded(is_local, exploded, &out_time)) {
274     return out_time;
275   } else if (is_local) {
276     // Hitting this branch means 00:00:00am of the current day
277     // does not exist (due to Daylight Saving Time in some countries
278     // where clocks are shifted at midnight). In this case, midnight
279     // should be defined as 01:00:00am.
280     exploded.hour = 1;
281     if (FromExploded(is_local, exploded, &out_time))
282       return out_time;
283   }
284   // This function must not fail.
285   NOTREACHED();
286   return Time();
287 }
288 
289 #if !defined(MOZ_SANDBOX)
290 // static
FromStringInternal(const char * time_string,bool is_local,Time * parsed_time)291 bool Time::FromStringInternal(const char* time_string,
292                               bool is_local,
293                               Time* parsed_time) {
294   DCHECK((time_string != nullptr) && (parsed_time != nullptr));
295 
296   if (time_string[0] == '\0')
297     return false;
298 
299   PRTime result_time = 0;
300   PRStatus result = PR_ParseTimeString(time_string,
301                                        is_local ? PR_FALSE : PR_TRUE,
302                                        &result_time);
303   if (PR_SUCCESS != result)
304     return false;
305 
306   result_time += kTimeTToMicrosecondsOffset;
307   *parsed_time = Time(result_time);
308   return true;
309 }
310 #endif
311 
312 // static
ExplodedMostlyEquals(const Exploded & lhs,const Exploded & rhs)313 bool Time::ExplodedMostlyEquals(const Exploded& lhs, const Exploded& rhs) {
314   return lhs.year == rhs.year && lhs.month == rhs.month &&
315          lhs.day_of_month == rhs.day_of_month && lhs.hour == rhs.hour &&
316          lhs.minute == rhs.minute && lhs.second == rhs.second &&
317          lhs.millisecond == rhs.millisecond;
318 }
319 
320 // static
FromMillisecondsSinceUnixEpoch(int64_t unix_milliseconds,Time * time)321 bool Time::FromMillisecondsSinceUnixEpoch(int64_t unix_milliseconds,
322                                           Time* time) {
323   // Adjust the provided time from milliseconds since the Unix epoch (1970) to
324   // microseconds since the Windows epoch (1601), avoiding overflows.
325   base::CheckedNumeric<int64_t> checked_microseconds_win_epoch =
326       unix_milliseconds;
327   checked_microseconds_win_epoch *= kMicrosecondsPerMillisecond;
328   checked_microseconds_win_epoch += kTimeTToMicrosecondsOffset;
329   if (!checked_microseconds_win_epoch.IsValid()) {
330     *time = base::Time(0);
331     return false;
332   }
333 
334   *time = Time(checked_microseconds_win_epoch.ValueOrDie());
335   return true;
336 }
337 
ToRoundedDownMillisecondsSinceUnixEpoch() const338 int64_t Time::ToRoundedDownMillisecondsSinceUnixEpoch() const {
339   // Adjust from Windows epoch (1601) to Unix epoch (1970).
340   int64_t microseconds = us_ - kTimeTToMicrosecondsOffset;
341 
342   // Round the microseconds towards -infinity.
343   if (microseconds >= 0) {
344     // In this case, rounding towards -infinity means rounding towards 0.
345     return microseconds / kMicrosecondsPerMillisecond;
346   } else {
347     return (microseconds - kMicrosecondsPerMillisecond + 1) /
348            kMicrosecondsPerMillisecond;
349   }
350 }
351 
operator <<(std::ostream & os,Time time)352 std::ostream& operator<<(std::ostream& os, Time time) {
353   Time::Exploded exploded;
354   time.UTCExplode(&exploded);
355   // Use StringPrintf because iostreams formatting is painful.
356   return os << StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d UTC",
357                             exploded.year,
358                             exploded.month,
359                             exploded.day_of_month,
360                             exploded.hour,
361                             exploded.minute,
362                             exploded.second,
363                             exploded.millisecond);
364 }
365 
366 // TimeTicks ------------------------------------------------------------------
367 
368 // static
Now()369 TimeTicks TimeTicks::Now() {
370   return internal::g_time_ticks_now_function();
371 }
372 
373 // static
UnixEpoch()374 TimeTicks TimeTicks::UnixEpoch() {
375   static const base::NoDestructor<base::TimeTicks> epoch([]() {
376     return subtle::TimeTicksNowIgnoringOverride() -
377            (subtle::TimeNowIgnoringOverride() - Time::UnixEpoch());
378   }());
379   return *epoch;
380 }
381 
SnappedToNextTick(TimeTicks tick_phase,TimeDelta tick_interval) const382 TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase,
383                                        TimeDelta tick_interval) const {
384   // |interval_offset| is the offset from |this| to the next multiple of
385   // |tick_interval| after |tick_phase|, possibly negative if in the past.
386   TimeDelta interval_offset = (tick_phase - *this) % tick_interval;
387   // If |this| is exactly on the interval (i.e. offset==0), don't adjust.
388   // Otherwise, if |tick_phase| was in the past, adjust forward to the next
389   // tick after |this|.
390   if (!interval_offset.is_zero() && tick_phase < *this)
391     interval_offset += tick_interval;
392   return *this + interval_offset;
393 }
394 
operator <<(std::ostream & os,TimeTicks time_ticks)395 std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
396   // This function formats a TimeTicks object as "bogo-microseconds".
397   // The origin and granularity of the count are platform-specific, and may very
398   // from run to run. Although bogo-microseconds usually roughly correspond to
399   // real microseconds, the only real guarantee is that the number never goes
400   // down during a single run.
401   const TimeDelta as_time_delta = time_ticks - TimeTicks();
402   return os << as_time_delta.InMicroseconds() << " bogo-microseconds";
403 }
404 
405 // ThreadTicks ----------------------------------------------------------------
406 
407 // static
Now()408 ThreadTicks ThreadTicks::Now() {
409   return internal::g_thread_ticks_now_function();
410 }
411 
operator <<(std::ostream & os,ThreadTicks thread_ticks)412 std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) {
413   const TimeDelta as_time_delta = thread_ticks - ThreadTicks();
414   return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds";
415 }
416 
417 // Time::Exploded -------------------------------------------------------------
418 
is_in_range(int value,int lo,int hi)419 inline bool is_in_range(int value, int lo, int hi) {
420   return lo <= value && value <= hi;
421 }
422 
HasValidValues() const423 bool Time::Exploded::HasValidValues() const {
424   return is_in_range(month, 1, 12) &&
425          is_in_range(day_of_week, 0, 6) &&
426          is_in_range(day_of_month, 1, 31) &&
427          is_in_range(hour, 0, 23) &&
428          is_in_range(minute, 0, 59) &&
429          is_in_range(second, 0, 60) &&
430          is_in_range(millisecond, 0, 999);
431 }
432 
433 }  // namespace base
434