|
1 // Copyright (c) 2006-2008 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.h" |
|
6 |
|
7 #ifdef OS_MACOSX |
|
8 #include <mach/mach_time.h> |
|
9 #endif |
|
10 #include <sys/time.h> |
|
11 #ifdef ANDROID |
|
12 #include <time64.h> |
|
13 #else |
|
14 #include <time.h> |
|
15 #endif |
|
16 #if defined(ANDROID) || defined(OS_POSIX) |
|
17 #include <unistd.h> |
|
18 #endif |
|
19 |
|
20 #include <limits> |
|
21 |
|
22 #include "base/basictypes.h" |
|
23 #include "base/logging.h" |
|
24 |
|
25 namespace base { |
|
26 |
|
27 // The Time routines in this file use standard POSIX routines, or almost- |
|
28 // standard routines in the case of timegm. We need to use a Mach-specific |
|
29 // function for TimeTicks::Now() on Mac OS X. |
|
30 |
|
31 // Time ----------------------------------------------------------------------- |
|
32 |
|
33 // Some functions in time.cc use time_t directly, so we provide a zero offset |
|
34 // for them. The epoch is 1970-01-01 00:00:00 UTC. |
|
35 // static |
|
36 const int64_t Time::kTimeTToMicrosecondsOffset = GG_INT64_C(0); |
|
37 |
|
38 // static |
|
39 Time Time::Now() { |
|
40 struct timeval tv; |
|
41 struct timezone tz = { 0, 0 }; // UTC |
|
42 if (gettimeofday(&tv, &tz) != 0) { |
|
43 DCHECK(0) << "Could not determine time of day"; |
|
44 } |
|
45 // Combine seconds and microseconds in a 64-bit field containing microseconds |
|
46 // since the epoch. That's enough for nearly 600 centuries. |
|
47 return tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec; |
|
48 } |
|
49 |
|
50 // static |
|
51 Time Time::NowFromSystemTime() { |
|
52 // Just use Now() because Now() returns the system time. |
|
53 return Now(); |
|
54 } |
|
55 |
|
56 // static |
|
57 Time Time::FromExploded(bool is_local, const Exploded& exploded) { |
|
58 struct tm timestruct; |
|
59 timestruct.tm_sec = exploded.second; |
|
60 timestruct.tm_min = exploded.minute; |
|
61 timestruct.tm_hour = exploded.hour; |
|
62 timestruct.tm_mday = exploded.day_of_month; |
|
63 timestruct.tm_mon = exploded.month - 1; |
|
64 timestruct.tm_year = exploded.year - 1900; |
|
65 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this |
|
66 timestruct.tm_yday = 0; // mktime/timegm ignore this |
|
67 timestruct.tm_isdst = -1; // attempt to figure it out |
|
68 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore |
|
69 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore |
|
70 |
|
71 time_t seconds; |
|
72 #ifdef ANDROID |
|
73 seconds = mktime(×truct); |
|
74 #else |
|
75 if (is_local) |
|
76 seconds = mktime(×truct); |
|
77 else |
|
78 seconds = timegm(×truct); |
|
79 #endif |
|
80 |
|
81 int64_t milliseconds; |
|
82 // Handle overflow. Clamping the range to what mktime and timegm might |
|
83 // return is the best that can be done here. It's not ideal, but it's better |
|
84 // than failing here or ignoring the overflow case and treating each time |
|
85 // overflow as one second prior to the epoch. |
|
86 if (seconds == -1 && |
|
87 (exploded.year < 1969 || exploded.year > 1970)) { |
|
88 // If exploded.year is 1969 or 1970, take -1 as correct, with the |
|
89 // time indicating 1 second prior to the epoch. (1970 is allowed to handle |
|
90 // time zone and DST offsets.) Otherwise, return the most future or past |
|
91 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. |
|
92 // |
|
93 // The minimum and maximum representible times that mktime and timegm could |
|
94 // return are used here instead of values outside that range to allow for |
|
95 // proper round-tripping between exploded and counter-type time |
|
96 // representations in the presence of possible truncation to time_t by |
|
97 // division and use with other functions that accept time_t. |
|
98 // |
|
99 // When representing the most distant time in the future, add in an extra |
|
100 // 999ms to avoid the time being less than any other possible value that |
|
101 // this function can return. |
|
102 if (exploded.year < 1969) { |
|
103 milliseconds = std::numeric_limits<time_t>::min() * |
|
104 kMillisecondsPerSecond; |
|
105 } else { |
|
106 milliseconds = (std::numeric_limits<time_t>::max() * |
|
107 kMillisecondsPerSecond) + |
|
108 kMillisecondsPerSecond - 1; |
|
109 } |
|
110 } else { |
|
111 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; |
|
112 } |
|
113 |
|
114 return Time(milliseconds * kMicrosecondsPerMillisecond); |
|
115 } |
|
116 |
|
117 void Time::Explode(bool is_local, Exploded* exploded) const { |
|
118 // Time stores times with microsecond resolution, but Exploded only carries |
|
119 // millisecond resolution, so begin by being lossy. |
|
120 int64_t milliseconds = us_ / kMicrosecondsPerMillisecond; |
|
121 time_t seconds = milliseconds / kMillisecondsPerSecond; |
|
122 |
|
123 struct tm timestruct; |
|
124 if (is_local) |
|
125 localtime_r(&seconds, ×truct); |
|
126 else |
|
127 gmtime_r(&seconds, ×truct); |
|
128 |
|
129 exploded->year = timestruct.tm_year + 1900; |
|
130 exploded->month = timestruct.tm_mon + 1; |
|
131 exploded->day_of_week = timestruct.tm_wday; |
|
132 exploded->day_of_month = timestruct.tm_mday; |
|
133 exploded->hour = timestruct.tm_hour; |
|
134 exploded->minute = timestruct.tm_min; |
|
135 exploded->second = timestruct.tm_sec; |
|
136 exploded->millisecond = milliseconds % kMillisecondsPerSecond; |
|
137 } |
|
138 |
|
139 // TimeTicks ------------------------------------------------------------------ |
|
140 |
|
141 // static |
|
142 TimeTicks TimeTicks::Now() { |
|
143 uint64_t absolute_micro; |
|
144 |
|
145 #if defined(OS_MACOSX) |
|
146 static mach_timebase_info_data_t timebase_info; |
|
147 if (timebase_info.denom == 0) { |
|
148 // Zero-initialization of statics guarantees that denom will be 0 before |
|
149 // calling mach_timebase_info. mach_timebase_info will never set denom to |
|
150 // 0 as that would be invalid, so the zero-check can be used to determine |
|
151 // whether mach_timebase_info has already been called. This is |
|
152 // recommended by Apple's QA1398. |
|
153 kern_return_t kr = mach_timebase_info(&timebase_info); |
|
154 DCHECK(kr == KERN_SUCCESS); |
|
155 } |
|
156 |
|
157 // mach_absolute_time is it when it comes to ticks on the Mac. Other calls |
|
158 // with less precision (such as TickCount) just call through to |
|
159 // mach_absolute_time. |
|
160 |
|
161 // timebase_info converts absolute time tick units into nanoseconds. Convert |
|
162 // to microseconds up front to stave off overflows. |
|
163 absolute_micro = mach_absolute_time() / Time::kNanosecondsPerMicrosecond * |
|
164 timebase_info.numer / timebase_info.denom; |
|
165 |
|
166 // Don't bother with the rollover handling that the Windows version does. |
|
167 // With numer and denom = 1 (the expected case), the 64-bit absolute time |
|
168 // reported in nanoseconds is enough to last nearly 585 years. |
|
169 |
|
170 #elif defined(OS_OPENBSD) || defined(OS_POSIX) && \ |
|
171 defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 |
|
172 |
|
173 struct timespec ts; |
|
174 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { |
|
175 NOTREACHED() << "clock_gettime(CLOCK_MONOTONIC) failed."; |
|
176 return TimeTicks(); |
|
177 } |
|
178 |
|
179 absolute_micro = |
|
180 (static_cast<int64_t>(ts.tv_sec) * Time::kMicrosecondsPerSecond) + |
|
181 (static_cast<int64_t>(ts.tv_nsec) / Time::kNanosecondsPerMicrosecond); |
|
182 |
|
183 #else // _POSIX_MONOTONIC_CLOCK |
|
184 #error No usable tick clock function on this platform. |
|
185 #endif // _POSIX_MONOTONIC_CLOCK |
|
186 |
|
187 return TimeTicks(absolute_micro); |
|
188 } |
|
189 |
|
190 // static |
|
191 TimeTicks TimeTicks::HighResNow() { |
|
192 return Now(); |
|
193 } |
|
194 |
|
195 } // namespace base |