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 13 matching lines...) Expand all Loading... |
221 *time = Time(0); | 203 *time = Time(0); |
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 - kTimeTToMicrosecondsOffset) / |
232 kWindowsEpochDeltaSeconds - | 214 kMicrosecondsPerSecond) - |
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 |