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