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 <limits> 8#include <ostream> 9 10#include "base/float_util.h" 11#include "base/lazy_instance.h" 12#include "base/logging.h" 13#include "base/third_party/nspr/prtime.h" 14 15namespace base { 16 17// TimeDelta ------------------------------------------------------------------ 18 19// static 20TimeDelta TimeDelta::Max() { 21 return TimeDelta(std::numeric_limits<int64>::max()); 22} 23 24int TimeDelta::InDays() const { 25 if (is_max()) { 26 // Preserve max to prevent overflow. 27 return std::numeric_limits<int>::max(); 28 } 29 return static_cast<int>(delta_ / Time::kMicrosecondsPerDay); 30} 31 32int TimeDelta::InHours() const { 33 if (is_max()) { 34 // Preserve max to prevent overflow. 35 return std::numeric_limits<int>::max(); 36 } 37 return static_cast<int>(delta_ / Time::kMicrosecondsPerHour); 38} 39 40int TimeDelta::InMinutes() 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::kMicrosecondsPerMinute); 46} 47 48double TimeDelta::InSecondsF() const { 49 if (is_max()) { 50 // Preserve max to prevent overflow. 51 return std::numeric_limits<double>::infinity(); 52 } 53 return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond; 54} 55 56int64 TimeDelta::InSeconds() const { 57 if (is_max()) { 58 // Preserve max to prevent overflow. 59 return std::numeric_limits<int64>::max(); 60 } 61 return delta_ / Time::kMicrosecondsPerSecond; 62} 63 64double TimeDelta::InMillisecondsF() const { 65 if (is_max()) { 66 // Preserve max to prevent overflow. 67 return std::numeric_limits<double>::infinity(); 68 } 69 return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond; 70} 71 72int64 TimeDelta::InMilliseconds() const { 73 if (is_max()) { 74 // Preserve max to prevent overflow. 75 return std::numeric_limits<int64>::max(); 76 } 77 return delta_ / Time::kMicrosecondsPerMillisecond; 78} 79 80int64 TimeDelta::InMillisecondsRoundedUp() const { 81 if (is_max()) { 82 // Preserve max to prevent overflow. 83 return std::numeric_limits<int64>::max(); 84 } 85 return (delta_ + Time::kMicrosecondsPerMillisecond - 1) / 86 Time::kMicrosecondsPerMillisecond; 87} 88 89int64 TimeDelta::InMicroseconds() const { 90 if (is_max()) { 91 // Preserve max to prevent overflow. 92 return std::numeric_limits<int64>::max(); 93 } 94 return delta_; 95} 96 97// Time ----------------------------------------------------------------------- 98 99// static 100Time Time::Max() { 101 return Time(std::numeric_limits<int64>::max()); 102} 103 104// static 105Time Time::FromTimeT(time_t tt) { 106 if (tt == 0) 107 return Time(); // Preserve 0 so we can tell it doesn't exist. 108 if (tt == std::numeric_limits<time_t>::max()) 109 return Max(); 110 return Time((tt * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset); 111} 112 113time_t Time::ToTimeT() const { 114 if (is_null()) 115 return 0; // Preserve 0 so we can tell it doesn't exist. 116 if (is_max()) { 117 // Preserve max without offset to prevent overflow. 118 return std::numeric_limits<time_t>::max(); 119 } 120 if (std::numeric_limits<int64>::max() - kTimeTToMicrosecondsOffset <= us_) { 121 DLOG(WARNING) << "Overflow when converting base::Time with internal " << 122 "value " << us_ << " to time_t."; 123 return std::numeric_limits<time_t>::max(); 124 } 125 return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond; 126} 127 128// static 129Time Time::FromDoubleT(double dt) { 130 if (dt == 0 || IsNaN(dt)) 131 return Time(); // Preserve 0 so we can tell it doesn't exist. 132 if (dt == std::numeric_limits<double>::infinity()) 133 return Max(); 134 return Time(static_cast<int64>((dt * 135 static_cast<double>(kMicrosecondsPerSecond)) + 136 kTimeTToMicrosecondsOffset)); 137} 138 139double Time::ToDoubleT() const { 140 if (is_null()) 141 return 0; // Preserve 0 so we can tell it doesn't exist. 142 if (is_max()) { 143 // Preserve max without offset to prevent overflow. 144 return std::numeric_limits<double>::infinity(); 145 } 146 return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) / 147 static_cast<double>(kMicrosecondsPerSecond)); 148} 149 150#if defined(OS_POSIX) 151// static 152Time Time::FromTimeSpec(const timespec& ts) { 153 return FromDoubleT(ts.tv_sec + 154 static_cast<double>(ts.tv_nsec) / 155 base::Time::kNanosecondsPerSecond); 156} 157#endif 158 159// static 160Time Time::FromJsTime(double ms_since_epoch) { 161 // The epoch is a valid time, so this constructor doesn't interpret 162 // 0 as the null time. 163 if (ms_since_epoch == std::numeric_limits<double>::infinity()) 164 return Max(); 165 return Time(static_cast<int64>(ms_since_epoch * kMicrosecondsPerMillisecond) + 166 kTimeTToMicrosecondsOffset); 167} 168 169double Time::ToJsTime() const { 170 if (is_null()) { 171 // Preserve 0 so the invalid result doesn't depend on the platform. 172 return 0; 173 } 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 kMicrosecondsPerMillisecond); 180} 181 182int64 Time::ToJavaTime() const { 183 if (is_null()) { 184 // Preserve 0 so the invalid result doesn't depend on the platform. 185 return 0; 186 } 187 if (is_max()) { 188 // Preserve max without offset to prevent overflow. 189 return std::numeric_limits<int64>::max(); 190 } 191 return ((us_ - kTimeTToMicrosecondsOffset) / 192 kMicrosecondsPerMillisecond); 193} 194 195// static 196Time Time::UnixEpoch() { 197 Time time; 198 time.us_ = kTimeTToMicrosecondsOffset; 199 return time; 200} 201 202Time Time::LocalMidnight() const { 203 Exploded exploded; 204 LocalExplode(&exploded); 205 exploded.hour = 0; 206 exploded.minute = 0; 207 exploded.second = 0; 208 exploded.millisecond = 0; 209 return FromLocalExploded(exploded); 210} 211 212// static 213bool Time::FromStringInternal(const char* time_string, 214 bool is_local, 215 Time* parsed_time) { 216 DCHECK((time_string != NULL) && (parsed_time != NULL)); 217 218 if (time_string[0] == '\0') 219 return false; 220 221 PRTime result_time = 0; 222 PRStatus result = PR_ParseTimeString(time_string, 223 is_local ? PR_FALSE : PR_TRUE, 224 &result_time); 225 if (PR_SUCCESS != result) 226 return false; 227 228 result_time += kTimeTToMicrosecondsOffset; 229 *parsed_time = Time(result_time); 230 return true; 231} 232 233// Local helper class to hold the conversion from Time to TickTime at the 234// time of the Unix epoch. 235class UnixEpochSingleton { 236 public: 237 UnixEpochSingleton() 238 : unix_epoch_(TimeTicks::Now() - (Time::Now() - Time::UnixEpoch())) {} 239 240 TimeTicks unix_epoch() const { return unix_epoch_; } 241 242 private: 243 const TimeTicks unix_epoch_; 244 245 DISALLOW_COPY_AND_ASSIGN(UnixEpochSingleton); 246}; 247 248static LazyInstance<UnixEpochSingleton>::Leaky 249 leaky_unix_epoch_singleton_instance = LAZY_INSTANCE_INITIALIZER; 250 251// Static 252TimeTicks TimeTicks::UnixEpoch() { 253 return leaky_unix_epoch_singleton_instance.Get().unix_epoch(); 254} 255 256// Time::Exploded ------------------------------------------------------------- 257 258inline bool is_in_range(int value, int lo, int hi) { 259 return lo <= value && value <= hi; 260} 261 262bool Time::Exploded::HasValidValues() const { 263 return is_in_range(month, 1, 12) && 264 is_in_range(day_of_week, 0, 6) && 265 is_in_range(day_of_month, 1, 31) && 266 is_in_range(hour, 0, 23) && 267 is_in_range(minute, 0, 59) && 268 is_in_range(second, 0, 60) && 269 is_in_range(millisecond, 0, 999); 270} 271 272} // namespace base 273