Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/time/time.h" | 5 #include "base/time/time.h" |
| 6 | 6 |
| 7 #include <CoreFoundation/CFDate.h> | 7 #include <CoreFoundation/CFDate.h> |
| 8 #include <CoreFoundation/CFTimeZone.h> | 8 #include <CoreFoundation/CFTimeZone.h> |
| 9 #include <mach/mach.h> | 9 #include <mach/mach.h> |
| 10 #include <mach/mach_time.h> | 10 #include <mach/mach_time.h> |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 namespace base { | 111 namespace base { |
| 112 | 112 |
| 113 // The Time routines in this file use Mach and CoreFoundation APIs, since the | 113 // The Time routines in this file use Mach and CoreFoundation APIs, since the |
| 114 // POSIX definition of time_t in Mac OS X wraps around after 2038--and | 114 // POSIX definition of time_t in Mac OS X wraps around after 2038--and |
| 115 // there are already cookie expiration dates, etc., past that time out in | 115 // there are already cookie expiration dates, etc., past that time out in |
| 116 // the field. Using CFDate prevents that problem, and using mach_absolute_time | 116 // the field. Using CFDate prevents that problem, and using mach_absolute_time |
| 117 // for TimeTicks gives us nice high-resolution interval timing. | 117 // for TimeTicks gives us nice high-resolution interval timing. |
| 118 | 118 |
| 119 // Time ----------------------------------------------------------------------- | 119 // Time ----------------------------------------------------------------------- |
| 120 | 120 |
| 121 // Core Foundation uses a double second count since 2001-01-01 00:00:00 UTC. | |
| 122 // The UNIX epoch is 1970-01-01 00:00:00 UTC. | |
| 123 // Windows uses a Gregorian epoch of 1601. We need to match this internally | |
| 124 // so that our time representations match across all platforms. See bug 14734. | |
| 125 // irb(main):010:0> Time.at(0).getutc() | |
| 126 // => Thu Jan 01 00:00:00 UTC 1970 | |
| 127 // irb(main):011:0> Time.at(-11644473600).getutc() | |
| 128 // => Mon Jan 01 00:00:00 UTC 1601 | |
| 129 static const int64_t kWindowsEpochDeltaSeconds = INT64_C(11644473600); | |
| 130 | |
| 131 // static | |
| 132 const int64_t Time::kWindowsEpochDeltaMicroseconds = | |
| 133 kWindowsEpochDeltaSeconds * Time::kMicrosecondsPerSecond; | |
| 134 | |
| 135 // Some functions in time.cc use time_t directly, so we provide an offset | |
| 136 // to convert from time_t (Unix epoch) and internal (Windows epoch). | |
| 137 // static | |
| 138 const int64_t Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds; | |
| 139 | |
| 140 // static | 121 // static |
| 141 Time Time::Now() { | 122 Time Time::Now() { |
| 142 return FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent()); | 123 return FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent()); |
| 143 } | 124 } |
| 144 | 125 |
| 145 // static | 126 // static |
| 146 Time Time::FromCFAbsoluteTime(CFAbsoluteTime t) { | 127 Time Time::FromCFAbsoluteTime(CFAbsoluteTime t) { |
| 147 static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, | 128 static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, |
| 148 "CFAbsoluteTime must have an infinity value"); | 129 "CFAbsoluteTime must have an infinity value"); |
| 149 if (t == 0) | 130 if (t == 0) |
| 150 return Time(); // Consider 0 as a null Time. | 131 return Time(); // Consider 0 as a null Time. |
| 151 if (t == std::numeric_limits<CFAbsoluteTime>::infinity()) | 132 if (t == std::numeric_limits<CFAbsoluteTime>::infinity()) |
| 152 return Max(); | 133 return Max(); |
| 153 return Time(static_cast<int64_t>((t + kCFAbsoluteTimeIntervalSince1970) * | 134 return Time(static_cast<int64_t>((t + kCFAbsoluteTimeIntervalSince1970) * |
| 154 kMicrosecondsPerSecond) + | 135 kMicrosecondsPerSecond) + |
| 155 kWindowsEpochDeltaMicroseconds); | 136 kTimeTToMicrosecondsOffset); |
| 156 } | 137 } |
| 157 | 138 |
| 158 CFAbsoluteTime Time::ToCFAbsoluteTime() const { | 139 CFAbsoluteTime Time::ToCFAbsoluteTime() const { |
| 159 static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, | 140 static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, |
| 160 "CFAbsoluteTime must have an infinity value"); | 141 "CFAbsoluteTime must have an infinity value"); |
| 161 if (is_null()) | 142 if (is_null()) |
| 162 return 0; // Consider 0 as a null Time. | 143 return 0; // Consider 0 as a null Time. |
| 163 if (is_max()) | 144 if (is_max()) |
| 164 return std::numeric_limits<CFAbsoluteTime>::infinity(); | 145 return std::numeric_limits<CFAbsoluteTime>::infinity(); |
| 165 return (static_cast<CFAbsoluteTime>(us_ - kWindowsEpochDeltaMicroseconds) / | 146 return (static_cast<CFAbsoluteTime>(us_ - kTimeTToMicrosecondsOffset) / |
| 166 kMicrosecondsPerSecond) - kCFAbsoluteTimeIntervalSince1970; | 147 kMicrosecondsPerSecond) - |
| 148 kCFAbsoluteTimeIntervalSince1970; | |
| 167 } | 149 } |
| 168 | 150 |
| 169 // static | 151 // static |
| 170 Time Time::NowFromSystemTime() { | 152 Time Time::NowFromSystemTime() { |
| 171 // Just use Now() because Now() returns the system time. | 153 // Just use Now() because Now() returns the system time. |
| 172 return Now(); | 154 return Now(); |
| 173 } | 155 } |
| 174 | 156 |
| 175 // static | 157 // static |
| 176 bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { | 158 bool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 187 CFCalendarComposeAbsoluteTime( | 169 CFCalendarComposeAbsoluteTime( |
| 188 gregorian, &absolute_time, "yMdHmsS", exploded.year, exploded.month, | 170 gregorian, &absolute_time, "yMdHmsS", exploded.year, exploded.month, |
| 189 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, | 171 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, |
| 190 exploded.millisecond); | 172 exploded.millisecond); |
| 191 CFAbsoluteTime seconds = absolute_time + kCFAbsoluteTimeIntervalSince1970; | 173 CFAbsoluteTime seconds = absolute_time + kCFAbsoluteTimeIntervalSince1970; |
| 192 | 174 |
| 193 // CFAbsolutTime is typedef of double. Convert seconds to | 175 // CFAbsolutTime is typedef of double. Convert seconds to |
| 194 // microseconds and then cast to int64. If | 176 // microseconds and then cast to int64. If |
| 195 // it cannot be suited to int64, then fail to avoid overflows. | 177 // it cannot be suited to int64, then fail to avoid overflows. |
| 196 double microseconds = | 178 double microseconds = |
| 197 (seconds * kMicrosecondsPerSecond) + kWindowsEpochDeltaMicroseconds; | 179 (seconds * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset; |
| 198 if (microseconds > std::numeric_limits<int64_t>::max() || | 180 if (microseconds > std::numeric_limits<int64_t>::max() || |
| 199 microseconds < std::numeric_limits<int64_t>::min()) { | 181 microseconds < std::numeric_limits<int64_t>::min()) { |
| 200 *time = Time(0); | 182 *time = Time(0); |
| 201 return false; | 183 return false; |
| 202 } | 184 } |
| 203 | 185 |
| 204 base::Time converted_time = Time(static_cast<int64_t>(microseconds)); | 186 base::Time converted_time = Time(static_cast<int64_t>(microseconds)); |
| 205 | 187 |
| 206 // If |exploded.day_of_month| is set to 31 | 188 // If |exploded.day_of_month| is set to 31 |
| 207 // on a 28-30 day month, it will return the first day of the next month. | 189 // on a 28-30 day month, it will return the first day of the next month. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 222 return false; | 204 return false; |
| 223 } | 205 } |
| 224 | 206 |
| 225 void Time::Explode(bool is_local, Exploded* exploded) const { | 207 void Time::Explode(bool is_local, Exploded* exploded) const { |
| 226 // Avoid rounding issues, by only putting the integral number of seconds | 208 // Avoid rounding issues, by only putting the integral number of seconds |
| 227 // (rounded towards -infinity) into a |CFAbsoluteTime| (which is a |double|). | 209 // (rounded towards -infinity) into a |CFAbsoluteTime| (which is a |double|). |
| 228 int64_t microsecond = us_ % kMicrosecondsPerSecond; | 210 int64_t microsecond = us_ % kMicrosecondsPerSecond; |
| 229 if (microsecond < 0) | 211 if (microsecond < 0) |
| 230 microsecond += kMicrosecondsPerSecond; | 212 microsecond += kMicrosecondsPerSecond; |
| 231 CFAbsoluteTime seconds = ((us_ - microsecond) / kMicrosecondsPerSecond) - | 213 CFAbsoluteTime seconds = ((us_ - microsecond) / kMicrosecondsPerSecond) - |
| 232 kWindowsEpochDeltaSeconds - | 214 kTimeTToMicrosecondsOffset - |
|
miu
2017/05/18 02:52:38
Note: Trybot unit tests caught my erroneous replac
Lei Zhang
2017/05/18 19:06:13
Horray for tests!
| |
| 233 kCFAbsoluteTimeIntervalSince1970; | 215 kCFAbsoluteTimeIntervalSince1970; |
| 234 | 216 |
| 235 base::ScopedCFTypeRef<CFTimeZoneRef> time_zone( | 217 base::ScopedCFTypeRef<CFTimeZoneRef> time_zone( |
| 236 is_local | 218 is_local |
| 237 ? CFTimeZoneCopySystem() | 219 ? CFTimeZoneCopySystem() |
| 238 : CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0)); | 220 : CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0)); |
| 239 base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier( | 221 base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier( |
| 240 kCFAllocatorDefault, kCFGregorianCalendar)); | 222 kCFAllocatorDefault, kCFGregorianCalendar)); |
| 241 CFCalendarSetTimeZone(gregorian, time_zone); | 223 CFCalendarSetTimeZone(gregorian, time_zone); |
| 242 int second, day_of_week; | 224 int second, day_of_week; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 292 return Clock::MAC_MACH_ABSOLUTE_TIME; | 274 return Clock::MAC_MACH_ABSOLUTE_TIME; |
| 293 #endif // defined(OS_IOS) | 275 #endif // defined(OS_IOS) |
| 294 } | 276 } |
| 295 | 277 |
| 296 // static | 278 // static |
| 297 ThreadTicks ThreadTicks::Now() { | 279 ThreadTicks ThreadTicks::Now() { |
| 298 return ThreadTicks(ComputeThreadTicks()); | 280 return ThreadTicks(ComputeThreadTicks()); |
| 299 } | 281 } |
| 300 | 282 |
| 301 } // namespace base | 283 } // namespace base |
| OLD | NEW |