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) |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
81 return Time((tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec) + | 84 return Time((tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec) + |
82 kWindowsEpochDeltaMicroseconds); | 85 kWindowsEpochDeltaMicroseconds); |
83 } | 86 } |
84 | 87 |
85 // static | 88 // static |
86 Time Time::NowFromSystemTime() { | 89 Time Time::NowFromSystemTime() { |
87 // Just use Now() because Now() returns the system time. | 90 // Just use Now() because Now() returns the system time. |
88 return Now(); | 91 return Now(); |
89 } | 92 } |
90 | 93 |
94 // Define a system-specific SysTimeT that wraps either to a time_t or | |
brettw
2012/11/29 19:27:52
This should go in an anon. namespace at the top of
digit1
2012/11/30 14:10:15
Thanks, that makes sense. Done.
| |
95 // a time64_t depending on the host system. See crbug.com/162007 | |
96 #if defined(OS_ANDROID) | |
97 struct SysTimeT { | |
digit1
2012/11/29 13:49:30
A small comment here: I'm not really sure that a n
| |
98 typedef time64_t type; | |
99 | |
100 SysTimeT() : t(0) {} | |
101 | |
102 explicit SysTimeT(struct tm* timestruct, bool is_local) { | |
103 if (is_local) | |
104 t = mktime64(timestruct); | |
105 else | |
106 t = timegm64(timestruct); | |
107 } | |
108 | |
109 void ToTimeStruct(struct tm* timestruct, bool is_local) { | |
110 if (is_local) | |
111 localtime64_r(&t, timestruct); | |
112 else | |
113 gmtime64_r(&t, timestruct); | |
114 } | |
115 | |
116 time64_t t; | |
117 }; | |
118 #else | |
119 struct SysTimeT { | |
120 typedef time_t type; | |
121 | |
122 SysTimeT() : t(0) {} | |
123 | |
124 explicit SysTimeT(struct tm* timestruct, bool is_local) { | |
125 if (is_local) | |
126 t = mktime(timestruct); | |
127 else | |
128 t = timegm(timestruct); | |
129 } | |
130 | |
131 void ToTimeStruct(struct tm* timestruct, bool is_local) { | |
132 if (is_local) | |
133 localtime_r(&t, timestruct); | |
134 else | |
135 gmtime_r(&t, timestruct); | |
136 } | |
137 | |
138 time_t t; | |
139 }; | |
140 #endif | |
141 | |
91 void Time::Explode(bool is_local, Exploded* exploded) const { | 142 void Time::Explode(bool is_local, Exploded* exploded) const { |
92 // Time stores times with microsecond resolution, but Exploded only carries | 143 // Time stores times with microsecond resolution, but Exploded only carries |
93 // millisecond resolution, so begin by being lossy. Adjust from Windows | 144 // millisecond resolution, so begin by being lossy. Adjust from Windows |
94 // epoch (1601) to Unix epoch (1970); | 145 // epoch (1601) to Unix epoch (1970); |
95 int64 microseconds = us_ - kWindowsEpochDeltaMicroseconds; | 146 int64 microseconds = us_ - kWindowsEpochDeltaMicroseconds; |
96 // The following values are all rounded towards -infinity. | 147 // The following values are all rounded towards -infinity. |
97 int64 milliseconds; // Milliseconds since epoch. | 148 int64 milliseconds; // Milliseconds since epoch. |
98 time_t seconds; // Seconds since epoch. | 149 SysTimeT seconds; // Seconds since epoch. |
99 int millisecond; // Exploded millisecond value (0-999). | 150 int millisecond; // Exploded millisecond value (0-999). |
100 if (microseconds >= 0) { | 151 if (microseconds >= 0) { |
101 // Rounding towards -infinity <=> rounding towards 0, in this case. | 152 // Rounding towards -infinity <=> rounding towards 0, in this case. |
102 milliseconds = microseconds / kMicrosecondsPerMillisecond; | 153 milliseconds = microseconds / kMicrosecondsPerMillisecond; |
103 seconds = milliseconds / kMillisecondsPerSecond; | 154 seconds.t = milliseconds / kMillisecondsPerSecond; |
104 millisecond = milliseconds % kMillisecondsPerSecond; | 155 millisecond = milliseconds % kMillisecondsPerSecond; |
105 } else { | 156 } else { |
106 // Round these *down* (towards -infinity). | 157 // Round these *down* (towards -infinity). |
107 milliseconds = (microseconds - kMicrosecondsPerMillisecond + 1) / | 158 milliseconds = (microseconds - kMicrosecondsPerMillisecond + 1) / |
108 kMicrosecondsPerMillisecond; | 159 kMicrosecondsPerMillisecond; |
109 seconds = (milliseconds - kMillisecondsPerSecond + 1) / | 160 seconds.t = (milliseconds - kMillisecondsPerSecond + 1) / |
110 kMillisecondsPerSecond; | 161 kMillisecondsPerSecond; |
111 // Make this nonnegative (and between 0 and 999 inclusive). | 162 // Make this nonnegative (and between 0 and 999 inclusive). |
112 millisecond = milliseconds % kMillisecondsPerSecond; | 163 millisecond = milliseconds % kMillisecondsPerSecond; |
113 if (millisecond < 0) | 164 if (millisecond < 0) |
114 millisecond += kMillisecondsPerSecond; | 165 millisecond += kMillisecondsPerSecond; |
115 } | 166 } |
116 | 167 |
117 struct tm timestruct; | 168 struct tm timestruct; |
118 if (is_local) | 169 seconds.ToTimeStruct(×truct, is_local); |
119 localtime_r(&seconds, ×truct); | |
120 else | |
121 gmtime_r(&seconds, ×truct); | |
122 | 170 |
123 exploded->year = timestruct.tm_year + 1900; | 171 exploded->year = timestruct.tm_year + 1900; |
124 exploded->month = timestruct.tm_mon + 1; | 172 exploded->month = timestruct.tm_mon + 1; |
125 exploded->day_of_week = timestruct.tm_wday; | 173 exploded->day_of_week = timestruct.tm_wday; |
126 exploded->day_of_month = timestruct.tm_mday; | 174 exploded->day_of_month = timestruct.tm_mday; |
127 exploded->hour = timestruct.tm_hour; | 175 exploded->hour = timestruct.tm_hour; |
128 exploded->minute = timestruct.tm_min; | 176 exploded->minute = timestruct.tm_min; |
129 exploded->second = timestruct.tm_sec; | 177 exploded->second = timestruct.tm_sec; |
130 exploded->millisecond = millisecond; | 178 exploded->millisecond = millisecond; |
131 } | 179 } |
132 | 180 |
133 // static | 181 // static |
134 Time Time::FromExploded(bool is_local, const Exploded& exploded) { | 182 Time Time::FromExploded(bool is_local, const Exploded& exploded) { |
135 struct tm timestruct; | 183 struct tm timestruct; |
136 timestruct.tm_sec = exploded.second; | 184 timestruct.tm_sec = exploded.second; |
137 timestruct.tm_min = exploded.minute; | 185 timestruct.tm_min = exploded.minute; |
138 timestruct.tm_hour = exploded.hour; | 186 timestruct.tm_hour = exploded.hour; |
139 timestruct.tm_mday = exploded.day_of_month; | 187 timestruct.tm_mday = exploded.day_of_month; |
140 timestruct.tm_mon = exploded.month - 1; | 188 timestruct.tm_mon = exploded.month - 1; |
141 timestruct.tm_year = exploded.year - 1900; | 189 timestruct.tm_year = exploded.year - 1900; |
142 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this | 190 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this |
143 timestruct.tm_yday = 0; // mktime/timegm ignore this | 191 timestruct.tm_yday = 0; // mktime/timegm ignore this |
144 timestruct.tm_isdst = -1; // attempt to figure it out | 192 timestruct.tm_isdst = -1; // attempt to figure it out |
145 #if !defined(OS_NACL) && !defined(OS_SOLARIS) | 193 #if !defined(OS_NACL) && !defined(OS_SOLARIS) |
146 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore | 194 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 | 195 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore |
148 #endif | 196 #endif |
149 | 197 |
150 time_t seconds; | 198 SysTimeT seconds(×truct, is_local); |
151 if (is_local) | |
152 seconds = mktime(×truct); | |
153 else | |
154 seconds = timegm(×truct); | |
155 | 199 |
156 int64 milliseconds; | 200 int64 milliseconds; |
157 // Handle overflow. Clamping the range to what mktime and timegm might | 201 // 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 | 202 // 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 | 203 // than failing here or ignoring the overflow case and treating each time |
160 // overflow as one second prior to the epoch. | 204 // overflow as one second prior to the epoch. |
161 if (seconds == -1 && | 205 if (seconds.t == -1 && |
162 (exploded.year < 1969 || exploded.year > 1970)) { | 206 (exploded.year < 1969 || exploded.year > 1970)) { |
163 // If exploded.year is 1969 or 1970, take -1 as correct, with the | 207 // 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 | 208 // 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 | 209 // 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. | 210 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. |
167 // | 211 // |
168 // The minimum and maximum representible times that mktime and timegm could | 212 // 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 | 213 // return are used here instead of values outside that range to allow for |
170 // proper round-tripping between exploded and counter-type time | 214 // proper round-tripping between exploded and counter-type time |
171 // representations in the presence of possible truncation to time_t by | 215 // representations in the presence of possible truncation to time_t by |
172 // division and use with other functions that accept time_t. | 216 // division and use with other functions that accept time_t. |
173 // | 217 // |
174 // When representing the most distant time in the future, add in an extra | 218 // 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 | 219 // 999ms to avoid the time being less than any other possible value that |
176 // this function can return. | 220 // this function can return. |
177 if (exploded.year < 1969) { | 221 if (exploded.year < 1969) { |
178 milliseconds = std::numeric_limits<time_t>::min() * | 222 milliseconds = std::numeric_limits<SysTimeT::type>::min() * |
179 kMillisecondsPerSecond; | 223 kMillisecondsPerSecond; |
180 } else { | 224 } else { |
181 milliseconds = (std::numeric_limits<time_t>::max() * | 225 milliseconds = (std::numeric_limits<SysTimeT::type>::max() * |
182 kMillisecondsPerSecond) + | 226 kMillisecondsPerSecond) + |
183 kMillisecondsPerSecond - 1; | 227 kMillisecondsPerSecond - 1; |
184 } | 228 } |
185 } else { | 229 } else { |
186 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; | 230 milliseconds = seconds.t * kMillisecondsPerSecond + exploded.millisecond; |
187 } | 231 } |
188 | 232 |
189 // Adjust from Unix (1970) to Windows (1601) epoch. | 233 // Adjust from Unix (1970) to Windows (1601) epoch. |
190 return Time((milliseconds * kMicrosecondsPerMillisecond) + | 234 return Time((milliseconds * kMicrosecondsPerMillisecond) + |
191 kWindowsEpochDeltaMicroseconds); | 235 kWindowsEpochDeltaMicroseconds); |
192 } | 236 } |
193 | 237 |
194 // TimeTicks ------------------------------------------------------------------ | 238 // TimeTicks ------------------------------------------------------------------ |
195 // FreeBSD 6 has CLOCK_MONOLITHIC but defines _POSIX_MONOTONIC_CLOCK to -1. | 239 // FreeBSD 6 has CLOCK_MONOLITHIC but defines _POSIX_MONOTONIC_CLOCK to -1. |
196 #if (defined(OS_POSIX) && \ | 240 #if (defined(OS_POSIX) && \ |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
283 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; | 327 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; |
284 return result; | 328 return result; |
285 } | 329 } |
286 int64 us = us_ - kTimeTToMicrosecondsOffset; | 330 int64 us = us_ - kTimeTToMicrosecondsOffset; |
287 result.tv_sec = us / Time::kMicrosecondsPerSecond; | 331 result.tv_sec = us / Time::kMicrosecondsPerSecond; |
288 result.tv_usec = us % Time::kMicrosecondsPerSecond; | 332 result.tv_usec = us % Time::kMicrosecondsPerSecond; |
289 return result; | 333 return result; |
290 } | 334 } |
291 | 335 |
292 } // namespace base | 336 } // namespace base |
OLD | NEW |