remove redundant DCHECK that a size_t variable >= 0
[chromium-blink-merge.git] / base / time_mac.cc
blob883a35ba129a2d76bbf579f26d26d94ad3a55b39
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.
5 #include "base/time.h"
7 #include <CoreFoundation/CFDate.h>
8 #include <CoreFoundation/CFTimeZone.h>
9 #include <mach/mach_time.h>
10 #include <sys/sysctl.h>
11 #include <sys/time.h>
12 #include <sys/types.h>
13 #include <time.h>
15 #include "base/basictypes.h"
16 #include "base/logging.h"
17 #include "base/mac/scoped_cftyperef.h"
19 namespace {
21 uint64_t ComputeCurrentTicks() {
22 #if defined(OS_IOS)
23 // On iOS mach_absolute_time stops while the device is sleeping. Instead use
24 // now - KERN_BOOTTIME to get a time difference that is not impacted by clock
25 // changes. KERN_BOOTTIME will be updated by the system whenever the system
26 // clock change.
27 struct timeval boottime;
28 int mib[2] = {CTL_KERN, KERN_BOOTTIME};
29 size_t size = sizeof(boottime);
30 int kr = sysctl(mib, arraysize(mib), &boottime, &size, NULL, 0);
31 DCHECK_EQ(KERN_SUCCESS, kr);
32 base::TimeDelta time_difference = base::Time::Now() -
33 (base::Time::FromTimeT(boottime.tv_sec) +
34 base::TimeDelta::FromMicroseconds(boottime.tv_usec));
35 return time_difference.InMicroseconds();
36 #else
37 uint64_t absolute_micro;
39 static mach_timebase_info_data_t timebase_info;
40 if (timebase_info.denom == 0) {
41 // Zero-initialization of statics guarantees that denom will be 0 before
42 // calling mach_timebase_info. mach_timebase_info will never set denom to
43 // 0 as that would be invalid, so the zero-check can be used to determine
44 // whether mach_timebase_info has already been called. This is
45 // recommended by Apple's QA1398.
46 kern_return_t kr = mach_timebase_info(&timebase_info);
47 DCHECK_EQ(KERN_SUCCESS, kr);
50 // mach_absolute_time is it when it comes to ticks on the Mac. Other calls
51 // with less precision (such as TickCount) just call through to
52 // mach_absolute_time.
54 // timebase_info converts absolute time tick units into nanoseconds. Convert
55 // to microseconds up front to stave off overflows.
56 absolute_micro =
57 mach_absolute_time() / base::Time::kNanosecondsPerMicrosecond *
58 timebase_info.numer / timebase_info.denom;
60 // Don't bother with the rollover handling that the Windows version does.
61 // With numer and denom = 1 (the expected case), the 64-bit absolute time
62 // reported in nanoseconds is enough to last nearly 585 years.
63 return absolute_micro;
64 #endif // defined(OS_IOS)
67 } // namespace
69 namespace base {
71 // The Time routines in this file use Mach and CoreFoundation APIs, since the
72 // POSIX definition of time_t in Mac OS X wraps around after 2038--and
73 // there are already cookie expiration dates, etc., past that time out in
74 // the field. Using CFDate prevents that problem, and using mach_absolute_time
75 // for TimeTicks gives us nice high-resolution interval timing.
77 // Time -----------------------------------------------------------------------
79 // Core Foundation uses a double second count since 2001-01-01 00:00:00 UTC.
80 // The UNIX epoch is 1970-01-01 00:00:00 UTC.
81 // Windows uses a Gregorian epoch of 1601. We need to match this internally
82 // so that our time representations match across all platforms. See bug 14734.
83 // irb(main):010:0> Time.at(0).getutc()
84 // => Thu Jan 01 00:00:00 UTC 1970
85 // irb(main):011:0> Time.at(-11644473600).getutc()
86 // => Mon Jan 01 00:00:00 UTC 1601
87 static const int64 kWindowsEpochDeltaSeconds = GG_INT64_C(11644473600);
88 static const int64 kWindowsEpochDeltaMilliseconds =
89 kWindowsEpochDeltaSeconds * Time::kMillisecondsPerSecond;
91 // static
92 const int64 Time::kWindowsEpochDeltaMicroseconds =
93 kWindowsEpochDeltaSeconds * Time::kMicrosecondsPerSecond;
95 // Some functions in time.cc use time_t directly, so we provide an offset
96 // to convert from time_t (Unix epoch) and internal (Windows epoch).
97 // static
98 const int64 Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds;
100 // static
101 Time Time::Now() {
102 return FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent());
105 // static
106 Time Time::FromCFAbsoluteTime(CFAbsoluteTime t) {
107 if (t == 0)
108 return Time(); // Consider 0 as a null Time.
109 if (t == std::numeric_limits<CFAbsoluteTime>::max())
110 return Max();
111 return Time(static_cast<int64>(
112 (t + kCFAbsoluteTimeIntervalSince1970) * kMicrosecondsPerSecond) +
113 kWindowsEpochDeltaMicroseconds);
116 CFAbsoluteTime Time::ToCFAbsoluteTime() const {
117 if (is_null())
118 return 0; // Consider 0 as a null Time.
119 if (is_max())
120 return std::numeric_limits<CFAbsoluteTime>::max();
121 return (static_cast<CFAbsoluteTime>(us_ - kWindowsEpochDeltaMicroseconds) /
122 kMicrosecondsPerSecond) - kCFAbsoluteTimeIntervalSince1970;
125 // static
126 Time Time::NowFromSystemTime() {
127 // Just use Now() because Now() returns the system time.
128 return Now();
131 // static
132 Time Time::FromExploded(bool is_local, const Exploded& exploded) {
133 CFGregorianDate date;
134 date.second = exploded.second +
135 exploded.millisecond / static_cast<double>(kMillisecondsPerSecond);
136 date.minute = exploded.minute;
137 date.hour = exploded.hour;
138 date.day = exploded.day_of_month;
139 date.month = exploded.month;
140 date.year = exploded.year;
142 base::mac::ScopedCFTypeRef<CFTimeZoneRef>
143 time_zone(is_local ? CFTimeZoneCopySystem() : NULL);
144 CFAbsoluteTime seconds = CFGregorianDateGetAbsoluteTime(date, time_zone) +
145 kCFAbsoluteTimeIntervalSince1970;
146 return Time(static_cast<int64>(seconds * kMicrosecondsPerSecond) +
147 kWindowsEpochDeltaMicroseconds);
150 void Time::Explode(bool is_local, Exploded* exploded) const {
151 // Avoid rounding issues, by only putting the integral number of seconds
152 // (rounded towards -infinity) into a |CFAbsoluteTime| (which is a |double|).
153 int64 microsecond = us_ % kMicrosecondsPerSecond;
154 if (microsecond < 0)
155 microsecond += kMicrosecondsPerSecond;
156 CFAbsoluteTime seconds = ((us_ - microsecond) / kMicrosecondsPerSecond) -
157 kWindowsEpochDeltaSeconds -
158 kCFAbsoluteTimeIntervalSince1970;
160 base::mac::ScopedCFTypeRef<CFTimeZoneRef>
161 time_zone(is_local ? CFTimeZoneCopySystem() : NULL);
162 CFGregorianDate date = CFAbsoluteTimeGetGregorianDate(seconds, time_zone);
163 // 1 = Monday, ..., 7 = Sunday.
164 int cf_day_of_week = CFAbsoluteTimeGetDayOfWeek(seconds, time_zone);
166 exploded->year = date.year;
167 exploded->month = date.month;
168 exploded->day_of_week = cf_day_of_week % 7;
169 exploded->day_of_month = date.day;
170 exploded->hour = date.hour;
171 exploded->minute = date.minute;
172 // Make sure seconds are rounded down towards -infinity.
173 exploded->second = floor(date.second);
174 // Calculate milliseconds ourselves, since we rounded the |seconds|, making
175 // sure to round towards -infinity.
176 exploded->millisecond =
177 (microsecond >= 0) ? microsecond / kMicrosecondsPerMillisecond :
178 (microsecond - kMicrosecondsPerMillisecond + 1) /
179 kMicrosecondsPerMillisecond;
182 // TimeTicks ------------------------------------------------------------------
184 // static
185 TimeTicks TimeTicks::Now() {
186 return TimeTicks(ComputeCurrentTicks());
189 // static
190 TimeTicks TimeTicks::HighResNow() {
191 return Now();
194 // static
195 TimeTicks TimeTicks::NowFromSystemTraceTime() {
196 return HighResNow();
199 } // namespace base