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/strings/stringprintf.h"
     16 
     17 namespace base {
     18 
     19 // TimeDelta ------------------------------------------------------------------
     20 
     21 // static
     22 TimeDelta TimeDelta::Max() {
     23   return TimeDelta(std::numeric_limits<int64_t>::max());
     24 }
     25 
     26 int TimeDelta::InDays() const {
     27   if (is_max()) {
     28     // Preserve max to prevent overflow.
     29     return std::numeric_limits<int>::max();
     30   }
     31   return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
     32 }
     33 
     34 int TimeDelta::InHours() const {
     35   if (is_max()) {
     36     // Preserve max to prevent overflow.
     37     return std::numeric_limits<int>::max();
     38   }
     39   return static_cast<int>(delta_ / Time::kMicrosecondsPerHour);
     40 }
     41 
     42 int TimeDelta::InMinutes() const {
     43   if (is_max()) {
     44     // Preserve max to prevent overflow.
     45     return std::numeric_limits<int>::max();
     46   }
     47   return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute);
     48 }
     49 
     50 double TimeDelta::InSecondsF() const {
     51   if (is_max()) {
     52     // Preserve max to prevent overflow.
     53     return std::numeric_limits<double>::infinity();
     54   }
     55   return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond;
     56 }
     57 
     58 int64_t TimeDelta::InSeconds() const {
     59   if (is_max()) {
     60     // Preserve max to prevent overflow.
     61     return std::numeric_limits<int64_t>::max();
     62   }
     63   return delta_ / Time::kMicrosecondsPerSecond;
     64 }
     65 
     66 double TimeDelta::InMillisecondsF() const {
     67   if (is_max()) {
     68     // Preserve max to prevent overflow.
     69     return std::numeric_limits<double>::infinity();
     70   }
     71   return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond;
     72 }
     73 
     74 int64_t TimeDelta::InMilliseconds() const {
     75   if (is_max()) {
     76     // Preserve max to prevent overflow.
     77     return std::numeric_limits<int64_t>::max();
     78   }
     79   return delta_ / Time::kMicrosecondsPerMillisecond;
     80 }
     81 
     82 int64_t TimeDelta::InMillisecondsRoundedUp() const {
     83   if (is_max()) {
     84     // Preserve max to prevent overflow.
     85     return std::numeric_limits<int64_t>::max();
     86   }
     87   return (delta_ + Time::kMicrosecondsPerMillisecond - 1) /
     88       Time::kMicrosecondsPerMillisecond;
     89 }
     90 
     91 int64_t TimeDelta::InMicroseconds() const {
     92   if (is_max()) {
     93     // Preserve max to prevent overflow.
     94     return std::numeric_limits<int64_t>::max();
     95   }
     96   return delta_;
     97 }
     98 
     99 namespace time_internal {
    100 
    101 int64_t SaturatedAdd(TimeDelta delta, int64_t value) {
    102   CheckedNumeric<int64_t> rv(delta.delta_);
    103   rv += value;
    104   return FromCheckedNumeric(rv);
    105 }
    106 
    107 int64_t SaturatedSub(TimeDelta delta, int64_t value) {
    108   CheckedNumeric<int64_t> rv(delta.delta_);
    109   rv -= value;
    110   return FromCheckedNumeric(rv);
    111 }
    112 
    113 int64_t FromCheckedNumeric(const CheckedNumeric<int64_t> value) {
    114   if (value.IsValid())
    115     return value.ValueUnsafe();
    116 
    117   // We could return max/min but we don't really expose what the maximum delta
    118   // is. Instead, return max/(-max), which is something that clients can reason
    119   // about.
    120   // TODO(rvargas) crbug.com/332611: don't use internal values.
    121   int64_t limit = std::numeric_limits<int64_t>::max();
    122   if (value.validity() == internal::RANGE_UNDERFLOW)
    123     limit = -limit;
    124   return value.ValueOrDefault(limit);
    125 }
    126 
    127 }  // namespace time_internal
    128 
    129 std::ostream& operator<<(std::ostream& os, TimeDelta time_delta) {
    130   return os << time_delta.InSecondsF() << "s";
    131 }
    132 
    133 // Time -----------------------------------------------------------------------
    134 
    135 // static
    136 Time Time::Max() {
    137   return Time(std::numeric_limits<int64_t>::max());
    138 }
    139 
    140 // static
    141 Time Time::FromTimeT(time_t tt) {
    142   if (tt == 0)
    143     return Time();  // Preserve 0 so we can tell it doesn't exist.
    144   if (tt == std::numeric_limits<time_t>::max())
    145     return Max();
    146   return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSeconds(tt);
    147 }
    148 
    149 time_t Time::ToTimeT() const {
    150   if (is_null())
    151     return 0;  // Preserve 0 so we can tell it doesn't exist.
    152   if (is_max()) {
    153     // Preserve max without offset to prevent overflow.
    154     return std::numeric_limits<time_t>::max();
    155   }
    156   if (std::numeric_limits<int64_t>::max() - kTimeTToMicrosecondsOffset <= us_) {
    157     DLOG(WARNING) << "Overflow when converting base::Time with internal " <<
    158                      "value " << us_ << " to time_t.";
    159     return std::numeric_limits<time_t>::max();
    160   }
    161   return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond;
    162 }
    163 
    164 // static
    165 Time Time::FromDoubleT(double dt) {
    166   if (dt == 0 || std::isnan(dt))
    167     return Time();  // Preserve 0 so we can tell it doesn't exist.
    168   return Time(kTimeTToMicrosecondsOffset) + TimeDelta::FromSecondsD(dt);
    169 }
    170 
    171 double Time::ToDoubleT() const {
    172   if (is_null())
    173     return 0;  // Preserve 0 so we can tell it doesn't exist.
    174   if (is_max()) {
    175     // Preserve max without offset to prevent overflow.
    176     return std::numeric_limits<double>::infinity();
    177   }
    178   return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
    179           static_cast<double>(kMicrosecondsPerSecond));
    180 }
    181 
    182 #if defined(OS_POSIX)
    183 // static
    184 Time Time::FromTimeSpec(const timespec& ts) {
    185   return FromDoubleT(ts.tv_sec +
    186                      static_cast<double>(ts.tv_nsec) /
    187                          base::Time::kNanosecondsPerSecond);
    188 }
    189 #endif
    190 
    191 // static
    192 Time Time::FromJsTime(double ms_since_epoch) {
    193   // The epoch is a valid time, so this constructor doesn't interpret
    194   // 0 as the null time.
    195   return Time(kTimeTToMicrosecondsOffset) +
    196          TimeDelta::FromMillisecondsD(ms_since_epoch);
    197 }
    198 
    199 double Time::ToJsTime() const {
    200   if (is_null()) {
    201     // Preserve 0 so the invalid result doesn't depend on the platform.
    202     return 0;
    203   }
    204   if (is_max()) {
    205     // Preserve max without offset to prevent overflow.
    206     return std::numeric_limits<double>::infinity();
    207   }
    208   return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
    209           kMicrosecondsPerMillisecond);
    210 }
    211 
    212 int64_t Time::ToJavaTime() const {
    213   if (is_null()) {
    214     // Preserve 0 so the invalid result doesn't depend on the platform.
    215     return 0;
    216   }
    217   if (is_max()) {
    218     // Preserve max without offset to prevent overflow.
    219     return std::numeric_limits<int64_t>::max();
    220   }
    221   return ((us_ - kTimeTToMicrosecondsOffset) /
    222           kMicrosecondsPerMillisecond);
    223 }
    224 
    225 // static
    226 Time Time::UnixEpoch() {
    227   Time time;
    228   time.us_ = kTimeTToMicrosecondsOffset;
    229   return time;
    230 }
    231 
    232 Time Time::LocalMidnight() const {
    233   Exploded exploded;
    234   LocalExplode(&exploded);
    235   exploded.hour = 0;
    236   exploded.minute = 0;
    237   exploded.second = 0;
    238   exploded.millisecond = 0;
    239   return FromLocalExploded(exploded);
    240 }
    241 
    242 std::ostream& operator<<(std::ostream& os, Time time) {
    243   Time::Exploded exploded;
    244   time.UTCExplode(&exploded);
    245   // Use StringPrintf because iostreams formatting is painful.
    246   return os << StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d UTC",
    247                             exploded.year,
    248                             exploded.month,
    249                             exploded.day_of_month,
    250                             exploded.hour,
    251                             exploded.minute,
    252                             exploded.second,
    253                             exploded.millisecond);
    254 }
    255 
    256 // Local helper class to hold the conversion from Time to TickTime at the
    257 // time of the Unix epoch.
    258 class UnixEpochSingleton {
    259  public:
    260   UnixEpochSingleton()
    261       : unix_epoch_(TimeTicks::Now() - (Time::Now() - Time::UnixEpoch())) {}
    262 
    263   TimeTicks unix_epoch() const { return unix_epoch_; }
    264 
    265  private:
    266   const TimeTicks unix_epoch_;
    267 
    268   DISALLOW_COPY_AND_ASSIGN(UnixEpochSingleton);
    269 };
    270 
    271 TimeTicks TimeTicks::SnappedToNextTick(TimeTicks tick_phase,
    272                                        TimeDelta tick_interval) const {
    273   // |interval_offset| is the offset from |this| to the next multiple of
    274   // |tick_interval| after |tick_phase|, possibly negative if in the past.
    275   TimeDelta interval_offset = (tick_phase - *this) % tick_interval;
    276   // If |this| is exactly on the interval (i.e. offset==0), don't adjust.
    277   // Otherwise, if |tick_phase| was in the past, adjust forward to the next
    278   // tick after |this|.
    279   if (!interval_offset.is_zero() && tick_phase < *this)
    280     interval_offset += tick_interval;
    281   return *this + interval_offset;
    282 }
    283 
    284 std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks) {
    285   // This function formats a TimeTicks object as "bogo-microseconds".
    286   // The origin and granularity of the count are platform-specific, and may very
    287   // from run to run. Although bogo-microseconds usually roughly correspond to
    288   // real microseconds, the only real guarantee is that the number never goes
    289   // down during a single run.
    290   const TimeDelta as_time_delta = time_ticks - TimeTicks();
    291   return os << as_time_delta.InMicroseconds() << " bogo-microseconds";
    292 }
    293 
    294 std::ostream& operator<<(std::ostream& os, ThreadTicks thread_ticks) {
    295   const TimeDelta as_time_delta = thread_ticks - ThreadTicks();
    296   return os << as_time_delta.InMicroseconds() << " bogo-thread-microseconds";
    297 }
    298 
    299 // Time::Exploded -------------------------------------------------------------
    300 
    301 inline bool is_in_range(int value, int lo, int hi) {
    302   return lo <= value && value <= hi;
    303 }
    304 
    305 bool Time::Exploded::HasValidValues() const {
    306   return is_in_range(month, 1, 12) &&
    307          is_in_range(day_of_week, 0, 6) &&
    308          is_in_range(day_of_month, 1, 31) &&
    309          is_in_range(hour, 0, 23) &&
    310          is_in_range(minute, 0, 59) &&
    311          is_in_range(second, 0, 60) &&
    312          is_in_range(millisecond, 0, 999);
    313 }
    314 
    315 }  // namespace base
    316