Home | History | Annotate | Download | only in time
      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 
     40 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 
     48 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 
     61 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 
     69 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 
     77 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 
     85 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 
     93 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 
    101 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 
    109 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 
    122 int64_t TimeDelta::InMicroseconds() const {
    123   if (is_max()) {
    124     // Preserve max to prevent overflow.
    125     return std::numeric_limits<int64_t>::max();
    126   }
    127   return delta_;
    128 }
    129 
    130 double TimeDelta::InMicrosecondsF() const {
    131   if (is_max()) {
    132     // Preserve max to prevent overflow.
    133     return std::numeric_limits<double>::infinity();
    134   }
    135   return static_cast<double>(delta_);
    136 }
    137 
    138 int64_t TimeDelta::InNanoseconds() const {
    139   if (is_max()) {
    140     // Preserve max to prevent overflow.
    141     return std::numeric_limits<int64_t>::max();
    142   }
    143   return delta_ * Time::kNanosecondsPerMicrosecond;
    144 }
    145 
    146 namespace time_internal {
    147 
    148 int64_t SaturatedAdd(TimeDelta delta, int64_t value) {
    149   CheckedNumeric<int64_t> rv(delta.delta_);
    150   rv += value;
    151   if (rv.IsValid())
    152     return rv.ValueOrDie();
    153   // Positive RHS overflows. Negative RHS underflows.
    154   if (value < 0)
    155     return std::numeric_limits<int64_t>::min();
    156   return std::numeric_limits<int64_t>::max();
    157 }
    158 
    159 int64_t SaturatedSub(TimeDelta delta, int64_t value) {
    160   CheckedNumeric<int64_t> rv(delta.delta_);
    161   rv -= value;
    162   if (rv.IsValid())
    163     return rv.ValueOrDie();
    164   // Negative RHS overflows. Positive RHS underflows.
    165   if (value < 0)
    166     return std::numeric_limits<int64_t>::max();
    167   return std::numeric_limits<int64_t>::min();
    168 }
    169 
    170 }  // namespace time_internal
    171 
    172 std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) {
    173   return os << time_delta.InSecondsF() << " s";
    174 }
    175 
    176 // Time -----------------------------------------------------------------------
    177 
    178 // static
    179 Time Time::Now() {
    180   return internal::g_time_now_function();
    181 }
    182 
    183 // static
    184 Time Time::NowFromSystemTime() {
    185   // Just use g_time_now_function because it returns the system time.
    186   return internal::g_time_now_from_system_time_function();
    187 }
    188 
    189 // static
    190 Time Time::FromDeltaSinceWindowsEpoch(TimeDelta delta) {
    191   return Time(delta.InMicroseconds());
    192 }
    193 
    194 TimeDelta Time::ToDeltaSinceWindowsEpoch() const {
    195   return TimeDelta::FromMicroseconds(us_);
    196 }
    197 
    198 // static
    199 Time Time::FromTimeT(time_t tt) {
    200   if (tt == 0)
    201     return Time();  // Preserve 0 so we can tell it doesn't exist.
    202   if (tt == std::numeric_limits<time_t>::max())
    203     return Max();
    204   return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSeconds(tt);
    205 }
    206 
    207 time_t Time::ToTimeT() const {
    208   if (is_null())
    209     return 0;  // Preserve 0 so we can tell it doesn't exist.
    210   if (is_max()) {
    211     // Preserve max without offset to prevent overflow.
    212     return std::numeric_limits<time_t>::max();
    213   }
    214   if (std::numeric_limits<int64_t>::max() - kTimeTToMicrosecondsOffset <= us_) {
    215     DLOG(WARNING) << "Overflow when converting base::Time with internal " <<
    216                      "value " << us_ << " to time_t.";
    217     return std::numeric_limits<time_t>::max();
    218   }
    219   return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond;
    220 }
    221 
    222 // static
    223 Time Time::FromDoubleT(double dt) {
    224   if (dt == 0 || std::isnan(dt))
    225     return Time();  // Preserve 0 so we can tell it doesn't exist.
    226   return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSecondsD(dt);
    227 }
    228 
    229 double Time::ToDoubleT() const {
    230   if (is_null())
    231     return 0;  // Preserve 0 so we can tell it doesn't exist.
    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           static_cast<double>(kMicrosecondsPerSecond));
    238 }
    239 
    240 #if defined(OS_POSIX)
    241 // static
    242 Time Time::FromTimeSpec(const timespec& ts) {
    243   return FromDoubleT(ts.tv_sec +
    244                      static_cast<double>(ts.tv_nsec) /
    245                          base::Time::kNanosecondsPerSecond);
    246 }
    247 #endif
    248 
    249 // static
    250 Time Time::FromJsTime(double ms_since_epoch) {
    251   // The epoch is a valid time, so this constructor doesn't interpret
    252   // 0 as the null time.
    253   return Time(kTimeTToMicrosecondsOffset) +
    254          TimeDelta::FromMillisecondsD(ms_since_epoch);
    255 }
    256 
    257 double Time::ToJsTime() const {
    258   if (is_null()) {
    259     // Preserve 0 so the invalid result doesn't depend on the platform.
    260     return 0;
    261   }
    262   if (is_max()) {
    263     // Preserve max without offset to prevent overflow.
    264     return std::numeric_limits<double>::infinity();
    265   }
    266   return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
    267           kMicrosecondsPerMillisecond);
    268 }
    269 
    270 Time Time::FromJavaTime(int64_t ms_since_epoch) {
    271   return base::Time::UnixEpoch() +
    272          base::TimeDelta::FromMilliseconds(ms_since_epoch);
    273 }
    274 
    275 int64_t Time::ToJavaTime() const {
    276   if (is_null()) {
    277     // Preserve 0 so the invalid result doesn't depend on the platform.
    278     return 0;
    279   }
    280   if (is_max()) {
    281     // Preserve max without offset to prevent overflow.
    282     return std::numeric_limits<int64_t>::max();
    283   }
    284   return ((us_ - kTimeTToMicrosecondsOffset) /
    285           kMicrosecondsPerMillisecond);
    286 }
    287 
    288 // static
    289 Time Time::UnixEpoch() {
    290   Time time;
    291   time.us_ = kTimeTToMicrosecondsOffset;
    292   return time;
    293 }
    294 
    295 Time Time::LocalMidnight() const {
    296   Exploded exploded;
    297   LocalExplode(&exploded);
    298   exploded.hour = 0;
    299   exploded.minute = 0;
    300   exploded.second = 0;
    301   exploded.millisecond = 0;
    302   Time out_time;
    303   if (FromLocalExploded(exploded, &out_time))
    304     return out_time;
    305   // This function must not fail.
    306   NOTREACHED();
    307   return Time();
    308 }
    309 
    310 // static
    311 bool Time::FromStringInternal(const char* time_string,
    312                               bool is_local,
    313                               Time* parsed_time) {
    314   DCHECK((time_string != nullptr) && (parsed_time != nullptr));
    315 
    316   if (time_string[0] == '\0')
    317     return false;
    318 
    319   PRTime result_time = 0;
    320   PRStatus result = PR_ParseTimeString(time_string,
    321                                        is_local ? PR_FALSE : PR_TRUE,
    322                                        &result_time);
    323   if (PR_SUCCESS != result)
    324     return false;
    325 
    326   result_time += kTimeTToMicrosecondsOffset;
    327   *parsed_time = Time(result_time);
    328   return true;
    329 }
    330 
    331 // static
    332 bool Time::ExplodedMostlyEquals(const Exploded& lhs, const Exploded& rhs) {
    333   return lhs.year == rhs.year && lhs.month == rhs.month &&
    334          lhs.day_of_month == rhs.day_of_month && lhs.hour == rhs.hour &&
    335          lhs.minute == rhs.minute && lhs.second == rhs.second &&
    336          lhs.millisecond == rhs.millisecond;
    337 }
    338 
    339 std::ostream& operator<<(std::ostream& os, Time time) {
    340   Time::Exploded exploded;
    341   time.UTCExplode(&exploded);
    342   // Use StringPrintf because iostreams formatting is painful.
    343   return os << StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d UTC",
    344                             exploded.year,
    345                             exploded.month,
    346                             exploded.day_of_month,
    347                             exploded.hour,
    348                             exploded.minute,
    349                             exploded.second,
    350                             exploded.millisecond);
    351 }
    352 
    353 // TimeTicks ------------------------------------------------------------------
    354 
    355 // static
    356 TimeTicks TimeTicks::Now() {
    357   return internal::g_time_ticks_now_function();
    358 }
    359 
    360 // static
    361 TimeTicks TimeTicks::UnixEpoch() {
    362   static const base::NoDestructor<base::TimeTicks> epoch([]() {
    363     return subtle::TimeTicksNowIgnoringOverride() -
    364            (subtle::TimeNowIgnoringOverride() - Time::UnixEpoch());
    365   }());
    366   return *epoch;
    367 }
    368 
    369 TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase,
    370                                        TimeDelta tick_interval) const {
    371   // |interval_offset| is the offset from |this| to the next multiple of
    372   // |tick_interval| after |tick_phase|, possibly negative if in the past.
    373   TimeDelta interval_offset = (tick_phase - *this) % tick_interval;
    374   // If |this| is exactly on the interval (i.e. offset==0), don't adjust.
    375   // Otherwise, if |tick_phase| was in the past, adjust forward to the next
    376   // tick after |this|.
    377   if (!interval_offset.is_zero() && tick_phase < *this)
    378     interval_offset += tick_interval;
    379   return *this + interval_offset;
    380 }
    381 
    382 std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
    383   // This function formats a TimeTicks object as "bogo-microseconds".
    384   // The origin and granularity of the count are platform-specific, and may very
    385   // from run to run. Although bogo-microseconds usually roughly correspond to
    386   // real microseconds, the only real guarantee is that the number never goes
    387   // down during a single run.
    388   const TimeDelta as_time_delta = time_ticks - TimeTicks();
    389   return os << as_time_delta.InMicroseconds() << " bogo-microseconds";
    390 }
    391 
    392 // ThreadTicks ----------------------------------------------------------------
    393 
    394 // static
    395 ThreadTicks ThreadTicks::Now() {
    396   return internal::g_thread_ticks_now_function();
    397 }
    398 
    399 std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) {
    400   const TimeDelta as_time_delta = thread_ticks - ThreadTicks();
    401   return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds";
    402 }
    403 
    404 // Time::Exploded -------------------------------------------------------------
    405 
    406 inline bool is_in_range(int value, int lo, int hi) {
    407   return lo <= value && value <= hi;
    408 }
    409 
    410 bool Time::Exploded::HasValidValues() const {
    411   return is_in_range(month, 1, 12) &&
    412          is_in_range(day_of_week, 0, 6) &&
    413          is_in_range(day_of_month, 1, 31) &&
    414          is_in_range(hour, 0, 23) &&
    415          is_in_range(minute, 0, 59) &&
    416          is_in_range(second, 0, 60) &&
    417          is_in_range(millisecond, 0, 999);
    418 }
    419 
    420 }  // namespace base
    421