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.
7 #include <CoreFoundation/CFDate.h>
8 #include <CoreFoundation/CFTimeZone.h>
9 #include <mach/mach_time.h>
10 #include <sys/sysctl.h>
12 #include <sys/types.h>
15 #include "base/basictypes.h"
16 #include "base/logging.h"
17 #include "base/mac/scoped_cftyperef.h"
21 uint64_t ComputeCurrentTicks() {
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
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();
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.
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)
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
;
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).
98 const int64
Time::kTimeTToMicrosecondsOffset
= kWindowsEpochDeltaMicroseconds
;
102 return FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent());
106 Time
Time::FromCFAbsoluteTime(CFAbsoluteTime t
) {
108 return Time(); // Consider 0 as a null Time.
109 if (t
== std::numeric_limits
<CFAbsoluteTime
>::max())
111 return Time(static_cast<int64
>(
112 (t
+ kCFAbsoluteTimeIntervalSince1970
) * kMicrosecondsPerSecond
) +
113 kWindowsEpochDeltaMicroseconds
);
116 CFAbsoluteTime
Time::ToCFAbsoluteTime() const {
118 return 0; // Consider 0 as a null Time.
120 return std::numeric_limits
<CFAbsoluteTime
>::max();
121 return (static_cast<CFAbsoluteTime
>(us_
- kWindowsEpochDeltaMicroseconds
) /
122 kMicrosecondsPerSecond
) - kCFAbsoluteTimeIntervalSince1970
;
126 Time
Time::NowFromSystemTime() {
127 // Just use Now() because Now() returns the system time.
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
;
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 ------------------------------------------------------------------
185 TimeTicks
TimeTicks::Now() {
186 return TimeTicks(ComputeCurrentTicks());
190 TimeTicks
TimeTicks::HighResNow() {
195 TimeTicks
TimeTicks::NowFromSystemTraceTime() {