| 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 |