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/time.h" | 5 #include "base/time/time.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <sys/time.h> | 8 #include <sys/time.h> |
9 #include <time.h> | 9 #include <time.h> |
10 #if defined(OS_ANDROID) && !defined(__LP64__) | 10 #if defined(OS_ANDROID) && !defined(__LP64__) |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 timestruct.tm_mon = exploded.month - 1; | 235 timestruct.tm_mon = exploded.month - 1; |
236 timestruct.tm_year = exploded.year - 1900; | 236 timestruct.tm_year = exploded.year - 1900; |
237 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this | 237 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this |
238 timestruct.tm_yday = 0; // mktime/timegm ignore this | 238 timestruct.tm_yday = 0; // mktime/timegm ignore this |
239 timestruct.tm_isdst = -1; // attempt to figure it out | 239 timestruct.tm_isdst = -1; // attempt to figure it out |
240 #if !defined(OS_NACL) && !defined(OS_SOLARIS) | 240 #if !defined(OS_NACL) && !defined(OS_SOLARIS) |
241 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore | 241 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore |
242 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore | 242 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore |
243 #endif | 243 #endif |
244 | 244 |
245 int64_t milliseconds; | |
246 SysTime seconds; | 245 SysTime seconds; |
247 | 246 |
248 // Certain exploded dates do not really exist due to daylight saving times, | 247 // Certain exploded dates do not really exist due to daylight saving times, |
249 // and this causes mktime() to return implementation-defined values when | 248 // and this causes mktime() to return implementation-defined values when |
250 // tm_isdst is set to -1. On Android, the function will return -1, while the | 249 // tm_isdst is set to -1. On Android, the function will return -1, while the |
251 // C libraries of other platforms typically return a liberally-chosen value. | 250 // C libraries of other platforms typically return a liberally-chosen value. |
252 // Handling this requires the special code below. | 251 // Handling this requires the special code below. |
253 | 252 |
254 // SysTimeFromTimeStruct() modifies the input structure, save current value. | 253 // SysTimeFromTimeStruct() modifies the input structure, save current value. |
255 struct tm timestruct0 = timestruct; | 254 struct tm timestruct0 = timestruct; |
(...skipping 17 matching lines...) Expand all Loading... |
273 else if (seconds_isdst1 < 0) | 272 else if (seconds_isdst1 < 0) |
274 seconds = seconds_isdst0; | 273 seconds = seconds_isdst0; |
275 else | 274 else |
276 seconds = std::min(seconds_isdst0, seconds_isdst1); | 275 seconds = std::min(seconds_isdst0, seconds_isdst1); |
277 } | 276 } |
278 | 277 |
279 // Handle overflow. Clamping the range to what mktime and timegm might | 278 // Handle overflow. Clamping the range to what mktime and timegm might |
280 // return is the best that can be done here. It's not ideal, but it's better | 279 // return is the best that can be done here. It's not ideal, but it's better |
281 // than failing here or ignoring the overflow case and treating each time | 280 // than failing here or ignoring the overflow case and treating each time |
282 // overflow as one second prior to the epoch. | 281 // overflow as one second prior to the epoch. |
| 282 int64_t milliseconds = 0; |
283 if (seconds == -1 && | 283 if (seconds == -1 && |
284 (exploded.year < 1969 || exploded.year > 1970)) { | 284 (exploded.year < 1969 || exploded.year > 1970)) { |
285 // If exploded.year is 1969 or 1970, take -1 as correct, with the | 285 // If exploded.year is 1969 or 1970, take -1 as correct, with the |
286 // time indicating 1 second prior to the epoch. (1970 is allowed to handle | 286 // time indicating 1 second prior to the epoch. (1970 is allowed to handle |
287 // time zone and DST offsets.) Otherwise, return the most future or past | 287 // time zone and DST offsets.) Otherwise, return the most future or past |
288 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. | 288 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. |
289 // | 289 // |
290 // The minimum and maximum representible times that mktime and timegm could | 290 // The minimum and maximum representible times that mktime and timegm could |
291 // return are used here instead of values outside that range to allow for | 291 // return are used here instead of values outside that range to allow for |
292 // proper round-tripping between exploded and counter-type time | 292 // proper round-tripping between exploded and counter-type time |
(...skipping 12 matching lines...) Expand all Loading... |
305 const int64_t max_seconds = (sizeof(SysTime) < sizeof(int64_t)) | 305 const int64_t max_seconds = (sizeof(SysTime) < sizeof(int64_t)) |
306 ? std::numeric_limits<SysTime>::max() | 306 ? std::numeric_limits<SysTime>::max() |
307 : std::numeric_limits<int32_t>::max(); | 307 : std::numeric_limits<int32_t>::max(); |
308 if (exploded.year < 1969) { | 308 if (exploded.year < 1969) { |
309 milliseconds = min_seconds * kMillisecondsPerSecond; | 309 milliseconds = min_seconds * kMillisecondsPerSecond; |
310 } else { | 310 } else { |
311 milliseconds = max_seconds * kMillisecondsPerSecond; | 311 milliseconds = max_seconds * kMillisecondsPerSecond; |
312 milliseconds += (kMillisecondsPerSecond - 1); | 312 milliseconds += (kMillisecondsPerSecond - 1); |
313 } | 313 } |
314 } else { | 314 } else { |
315 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; | 315 base::CheckedNumeric<int64_t> checked_millis = seconds; |
| 316 checked_millis *= kMillisecondsPerSecond; |
| 317 checked_millis += exploded.millisecond; |
| 318 if (!checked_millis.IsValid()) { |
| 319 *time = base::Time(0); |
| 320 return false; |
| 321 } |
| 322 milliseconds = checked_millis.ValueOrDie(); |
316 } | 323 } |
317 | 324 |
318 // Adjust from Unix (1970) to Windows (1601) epoch. | 325 // Adjust from Unix (1970) to Windows (1601) epoch avoiding overflows. |
319 base::Time converted_time = | 326 base::CheckedNumeric<int64_t> checked_microseconds_win_epoch = milliseconds; |
320 Time((milliseconds * kMicrosecondsPerMillisecond) + | 327 checked_microseconds_win_epoch *= kMicrosecondsPerMillisecond; |
321 kWindowsEpochDeltaMicroseconds); | 328 checked_microseconds_win_epoch += kWindowsEpochDeltaMicroseconds; |
| 329 if (!checked_microseconds_win_epoch.IsValid()) { |
| 330 *time = base::Time(0); |
| 331 return false; |
| 332 } |
| 333 base::Time converted_time(checked_microseconds_win_epoch.ValueOrDie()); |
322 | 334 |
323 // If |exploded.day_of_month| is set to 31 on a 28-30 day month, it will | 335 // If |exploded.day_of_month| is set to 31 on a 28-30 day month, it will |
324 // return the first day of the next month. Thus round-trip the time and | 336 // return the first day of the next month. Thus round-trip the time and |
325 // compare the initial |exploded| with |utc_to_exploded| time. | 337 // compare the initial |exploded| with |utc_to_exploded| time. |
326 base::Time::Exploded to_exploded; | 338 base::Time::Exploded to_exploded; |
327 if (!is_local) | 339 if (!is_local) |
328 converted_time.UTCExplode(&to_exploded); | 340 converted_time.UTCExplode(&to_exploded); |
329 else | 341 else |
330 converted_time.LocalExplode(&to_exploded); | 342 converted_time.LocalExplode(&to_exploded); |
331 | 343 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; | 409 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; |
398 return result; | 410 return result; |
399 } | 411 } |
400 int64_t us = us_ - kTimeTToMicrosecondsOffset; | 412 int64_t us = us_ - kTimeTToMicrosecondsOffset; |
401 result.tv_sec = us / Time::kMicrosecondsPerSecond; | 413 result.tv_sec = us / Time::kMicrosecondsPerSecond; |
402 result.tv_usec = us % Time::kMicrosecondsPerSecond; | 414 result.tv_usec = us % Time::kMicrosecondsPerSecond; |
403 return result; | 415 return result; |
404 } | 416 } |
405 | 417 |
406 } // namespace base | 418 } // namespace base |
OLD | NEW |