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 15 namespace base { 16 17 // TimeDelta ------------------------------------------------------------------ 18 19 // static 20 TimeDelta TimeDelta::Max() { 21 return TimeDelta(std::numeric_limits<int64>::max()); 22 } 23 24 int 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 32 int 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 40 int 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 48 double 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 56 int64 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 64 double 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 72 int64 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 80 int64 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 89 int64 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 100 Time Time::Max() { 101 return Time(std::numeric_limits<int64>::max()); 102 } 103 104 // static 105 Time 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 113 time_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 129 Time 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 139 double 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 152 Time 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 160 Time 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 169 double 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 182 int64 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 196 Time Time::UnixEpoch() { 197 Time time; 198 time.us_ = kTimeTToMicrosecondsOffset; 199 return time; 200 } 201 202 Time 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 213 bool 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. 235 class 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 248 static LazyInstance<UnixEpochSingleton>::Leaky 249 leaky_unix_epoch_singleton_instance = LAZY_INSTANCE_INITIALIZER; 250 251 // Static 252 TimeTicks TimeTicks::UnixEpoch() { 253 return leaky_unix_epoch_singleton_instance.Get().unix_epoch(); 254 } 255 256 // Time::Exploded ------------------------------------------------------------- 257 258 inline bool is_in_range(int value, int lo, int hi) { 259 return lo <= value && value <= hi; 260 } 261 262 bool 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