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