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