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.h" | 5 #include "base/time.h" |
6 | 6 |
7 #include <sys/time.h> | 7 #include <sys/time.h> |
8 #include <time.h> | 8 #include <time.h> |
| 9 #if defined(OS_ANDROID) |
| 10 #include <time64.h> |
| 11 #endif |
9 #include <unistd.h> | 12 #include <unistd.h> |
10 | 13 |
11 #include <limits> | 14 #include <limits> |
12 | 15 |
13 #include "base/basictypes.h" | 16 #include "base/basictypes.h" |
14 #include "base/logging.h" | 17 #include "base/logging.h" |
15 | 18 |
16 #if defined(OS_ANDROID) | 19 #if defined(OS_ANDROID) |
17 #include "base/os_compat_android.h" | 20 #include "base/os_compat_android.h" |
18 #elif defined(OS_NACL) | 21 #elif defined(OS_NACL) |
19 #include "base/os_compat_nacl.h" | 22 #include "base/os_compat_nacl.h" |
20 #endif | 23 #endif |
21 | 24 |
| 25 namespace { |
| 26 |
| 27 // Define a system-specific SysTime that wraps either to a time_t or |
| 28 // a time64_t depending on the host system, and associated convertion. |
| 29 // See crbug.com/162007 |
| 30 #if defined(OS_ANDROID) |
| 31 typedef time64_t SysTime; |
| 32 |
| 33 SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) { |
| 34 if (is_local) |
| 35 return mktime64(timestruct); |
| 36 else |
| 37 return timegm64(timestruct); |
| 38 } |
| 39 |
| 40 void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) { |
| 41 if (is_local) |
| 42 localtime64_r(&t, timestruct); |
| 43 else |
| 44 gmtime64_r(&t, timestruct); |
| 45 } |
| 46 |
| 47 #else // OS_ANDROID |
| 48 typedef time_t SysTime; |
| 49 |
| 50 SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) { |
| 51 if (is_local) |
| 52 return mktime(timestruct); |
| 53 else |
| 54 return timegm(timestruct); |
| 55 } |
| 56 |
| 57 void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) { |
| 58 if (is_local) |
| 59 localtime_r(&t, timestruct); |
| 60 else |
| 61 gmtime_r(&t, timestruct); |
| 62 } |
| 63 #endif // OS_ANDROID |
| 64 |
| 65 } // namespace |
| 66 |
22 namespace base { | 67 namespace base { |
23 | 68 |
24 #if defined(OS_ANDROID) | 69 #if defined(OS_ANDROID) |
25 #define _POSIX_MONOTONIC_CLOCK 1 | 70 #define _POSIX_MONOTONIC_CLOCK 1 |
26 #endif | 71 #endif |
27 | 72 |
28 struct timespec TimeDelta::ToTimeSpec() const { | 73 struct timespec TimeDelta::ToTimeSpec() const { |
29 int64 microseconds = InMicroseconds(); | 74 int64 microseconds = InMicroseconds(); |
30 time_t seconds = 0; | 75 time_t seconds = 0; |
31 if (microseconds >= Time::kMicrosecondsPerSecond) { | 76 if (microseconds >= Time::kMicrosecondsPerSecond) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 return Now(); | 133 return Now(); |
89 } | 134 } |
90 | 135 |
91 void Time::Explode(bool is_local, Exploded* exploded) const { | 136 void Time::Explode(bool is_local, Exploded* exploded) const { |
92 // Time stores times with microsecond resolution, but Exploded only carries | 137 // Time stores times with microsecond resolution, but Exploded only carries |
93 // millisecond resolution, so begin by being lossy. Adjust from Windows | 138 // millisecond resolution, so begin by being lossy. Adjust from Windows |
94 // epoch (1601) to Unix epoch (1970); | 139 // epoch (1601) to Unix epoch (1970); |
95 int64 microseconds = us_ - kWindowsEpochDeltaMicroseconds; | 140 int64 microseconds = us_ - kWindowsEpochDeltaMicroseconds; |
96 // The following values are all rounded towards -infinity. | 141 // The following values are all rounded towards -infinity. |
97 int64 milliseconds; // Milliseconds since epoch. | 142 int64 milliseconds; // Milliseconds since epoch. |
98 time_t seconds; // Seconds since epoch. | 143 SysTime seconds; // Seconds since epoch. |
99 int millisecond; // Exploded millisecond value (0-999). | 144 int millisecond; // Exploded millisecond value (0-999). |
100 if (microseconds >= 0) { | 145 if (microseconds >= 0) { |
101 // Rounding towards -infinity <=> rounding towards 0, in this case. | 146 // Rounding towards -infinity <=> rounding towards 0, in this case. |
102 milliseconds = microseconds / kMicrosecondsPerMillisecond; | 147 milliseconds = microseconds / kMicrosecondsPerMillisecond; |
103 seconds = milliseconds / kMillisecondsPerSecond; | 148 seconds = milliseconds / kMillisecondsPerSecond; |
104 millisecond = milliseconds % kMillisecondsPerSecond; | 149 millisecond = milliseconds % kMillisecondsPerSecond; |
105 } else { | 150 } else { |
106 // Round these *down* (towards -infinity). | 151 // Round these *down* (towards -infinity). |
107 milliseconds = (microseconds - kMicrosecondsPerMillisecond + 1) / | 152 milliseconds = (microseconds - kMicrosecondsPerMillisecond + 1) / |
108 kMicrosecondsPerMillisecond; | 153 kMicrosecondsPerMillisecond; |
109 seconds = (milliseconds - kMillisecondsPerSecond + 1) / | 154 seconds = (milliseconds - kMillisecondsPerSecond + 1) / |
110 kMillisecondsPerSecond; | 155 kMillisecondsPerSecond; |
111 // Make this nonnegative (and between 0 and 999 inclusive). | 156 // Make this nonnegative (and between 0 and 999 inclusive). |
112 millisecond = milliseconds % kMillisecondsPerSecond; | 157 millisecond = milliseconds % kMillisecondsPerSecond; |
113 if (millisecond < 0) | 158 if (millisecond < 0) |
114 millisecond += kMillisecondsPerSecond; | 159 millisecond += kMillisecondsPerSecond; |
115 } | 160 } |
116 | 161 |
117 struct tm timestruct; | 162 struct tm timestruct; |
118 if (is_local) | 163 SysTimeToTimeStruct(seconds, ×truct, is_local); |
119 localtime_r(&seconds, ×truct); | |
120 else | |
121 gmtime_r(&seconds, ×truct); | |
122 | 164 |
123 exploded->year = timestruct.tm_year + 1900; | 165 exploded->year = timestruct.tm_year + 1900; |
124 exploded->month = timestruct.tm_mon + 1; | 166 exploded->month = timestruct.tm_mon + 1; |
125 exploded->day_of_week = timestruct.tm_wday; | 167 exploded->day_of_week = timestruct.tm_wday; |
126 exploded->day_of_month = timestruct.tm_mday; | 168 exploded->day_of_month = timestruct.tm_mday; |
127 exploded->hour = timestruct.tm_hour; | 169 exploded->hour = timestruct.tm_hour; |
128 exploded->minute = timestruct.tm_min; | 170 exploded->minute = timestruct.tm_min; |
129 exploded->second = timestruct.tm_sec; | 171 exploded->second = timestruct.tm_sec; |
130 exploded->millisecond = millisecond; | 172 exploded->millisecond = millisecond; |
131 } | 173 } |
132 | 174 |
133 // static | 175 // static |
134 Time Time::FromExploded(bool is_local, const Exploded& exploded) { | 176 Time Time::FromExploded(bool is_local, const Exploded& exploded) { |
135 struct tm timestruct; | 177 struct tm timestruct; |
136 timestruct.tm_sec = exploded.second; | 178 timestruct.tm_sec = exploded.second; |
137 timestruct.tm_min = exploded.minute; | 179 timestruct.tm_min = exploded.minute; |
138 timestruct.tm_hour = exploded.hour; | 180 timestruct.tm_hour = exploded.hour; |
139 timestruct.tm_mday = exploded.day_of_month; | 181 timestruct.tm_mday = exploded.day_of_month; |
140 timestruct.tm_mon = exploded.month - 1; | 182 timestruct.tm_mon = exploded.month - 1; |
141 timestruct.tm_year = exploded.year - 1900; | 183 timestruct.tm_year = exploded.year - 1900; |
142 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this | 184 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this |
143 timestruct.tm_yday = 0; // mktime/timegm ignore this | 185 timestruct.tm_yday = 0; // mktime/timegm ignore this |
144 timestruct.tm_isdst = -1; // attempt to figure it out | 186 timestruct.tm_isdst = -1; // attempt to figure it out |
145 #if !defined(OS_NACL) && !defined(OS_SOLARIS) | 187 #if !defined(OS_NACL) && !defined(OS_SOLARIS) |
146 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore | 188 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore |
147 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore | 189 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore |
148 #endif | 190 #endif |
149 | 191 |
150 time_t seconds; | 192 SysTime seconds = SysTimeFromTimeStruct(×truct, is_local); |
151 if (is_local) | |
152 seconds = mktime(×truct); | |
153 else | |
154 seconds = timegm(×truct); | |
155 | 193 |
156 int64 milliseconds; | 194 int64 milliseconds; |
157 // Handle overflow. Clamping the range to what mktime and timegm might | 195 // Handle overflow. Clamping the range to what mktime and timegm might |
158 // return is the best that can be done here. It's not ideal, but it's better | 196 // return is the best that can be done here. It's not ideal, but it's better |
159 // than failing here or ignoring the overflow case and treating each time | 197 // than failing here or ignoring the overflow case and treating each time |
160 // overflow as one second prior to the epoch. | 198 // overflow as one second prior to the epoch. |
161 if (seconds == -1 && | 199 if (seconds == -1 && |
162 (exploded.year < 1969 || exploded.year > 1970)) { | 200 (exploded.year < 1969 || exploded.year > 1970)) { |
163 // If exploded.year is 1969 or 1970, take -1 as correct, with the | 201 // If exploded.year is 1969 or 1970, take -1 as correct, with the |
164 // time indicating 1 second prior to the epoch. (1970 is allowed to handle | 202 // time indicating 1 second prior to the epoch. (1970 is allowed to handle |
165 // time zone and DST offsets.) Otherwise, return the most future or past | 203 // time zone and DST offsets.) Otherwise, return the most future or past |
166 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. | 204 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. |
167 // | 205 // |
168 // The minimum and maximum representible times that mktime and timegm could | 206 // The minimum and maximum representible times that mktime and timegm could |
169 // return are used here instead of values outside that range to allow for | 207 // return are used here instead of values outside that range to allow for |
170 // proper round-tripping between exploded and counter-type time | 208 // proper round-tripping between exploded and counter-type time |
171 // representations in the presence of possible truncation to time_t by | 209 // representations in the presence of possible truncation to time_t by |
172 // division and use with other functions that accept time_t. | 210 // division and use with other functions that accept time_t. |
173 // | 211 // |
174 // When representing the most distant time in the future, add in an extra | 212 // When representing the most distant time in the future, add in an extra |
175 // 999ms to avoid the time being less than any other possible value that | 213 // 999ms to avoid the time being less than any other possible value that |
176 // this function can return. | 214 // this function can return. |
177 if (exploded.year < 1969) { | 215 if (exploded.year < 1969) { |
178 milliseconds = std::numeric_limits<time_t>::min() * | 216 milliseconds = std::numeric_limits<SysTime>::min() * |
179 kMillisecondsPerSecond; | 217 kMillisecondsPerSecond; |
180 } else { | 218 } else { |
181 milliseconds = (std::numeric_limits<time_t>::max() * | 219 milliseconds = (std::numeric_limits<SysTime>::max() * |
182 kMillisecondsPerSecond) + | 220 kMillisecondsPerSecond) + |
183 kMillisecondsPerSecond - 1; | 221 kMillisecondsPerSecond - 1; |
184 } | 222 } |
185 } else { | 223 } else { |
186 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; | 224 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; |
187 } | 225 } |
188 | 226 |
189 // Adjust from Unix (1970) to Windows (1601) epoch. | 227 // Adjust from Unix (1970) to Windows (1601) epoch. |
190 return Time((milliseconds * kMicrosecondsPerMillisecond) + | 228 return Time((milliseconds * kMicrosecondsPerMillisecond) + |
191 kWindowsEpochDeltaMicroseconds); | 229 kWindowsEpochDeltaMicroseconds); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; | 321 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; |
284 return result; | 322 return result; |
285 } | 323 } |
286 int64 us = us_ - kTimeTToMicrosecondsOffset; | 324 int64 us = us_ - kTimeTToMicrosecondsOffset; |
287 result.tv_sec = us / Time::kMicrosecondsPerSecond; | 325 result.tv_sec = us / Time::kMicrosecondsPerSecond; |
288 result.tv_usec = us % Time::kMicrosecondsPerSecond; | 326 result.tv_usec = us % Time::kMicrosecondsPerSecond; |
289 return result; | 327 return result; |
290 } | 328 } |
291 | 329 |
292 } // namespace base | 330 } // namespace base |
OLD | NEW |