Chromium Code Reviews| 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) | 10 #if defined(OS_ANDROID) |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 Time Time::FromExploded(bool is_local, const Exploded& exploded) { | 201 Time Time::FromExploded(bool is_local, const Exploded& exploded) { |
| 202 struct tm timestruct; | 202 struct tm timestruct; |
| 203 timestruct.tm_sec = exploded.second; | 203 timestruct.tm_sec = exploded.second; |
| 204 timestruct.tm_min = exploded.minute; | 204 timestruct.tm_min = exploded.minute; |
| 205 timestruct.tm_hour = exploded.hour; | 205 timestruct.tm_hour = exploded.hour; |
| 206 timestruct.tm_mday = exploded.day_of_month; | 206 timestruct.tm_mday = exploded.day_of_month; |
| 207 timestruct.tm_mon = exploded.month - 1; | 207 timestruct.tm_mon = exploded.month - 1; |
| 208 timestruct.tm_year = exploded.year - 1900; | 208 timestruct.tm_year = exploded.year - 1900; |
| 209 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this | 209 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this |
| 210 timestruct.tm_yday = 0; // mktime/timegm ignore this | 210 timestruct.tm_yday = 0; // mktime/timegm ignore this |
| 211 timestruct.tm_isdst = -1; // attempt to figure it out | 211 timestruct.tm_isdst = -1; // attempt to figure it out |
|
jar (doing other things)
2013/10/16 21:36:34
Did you consider using a definite isdst setting of
digit1
2013/10/17 14:00:27
That's an excellent idea. I've performed some more
| |
| 212 #if !defined(OS_NACL) && !defined(OS_SOLARIS) | 212 #if !defined(OS_NACL) && !defined(OS_SOLARIS) |
| 213 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore | 213 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore |
| 214 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore | 214 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore |
| 215 #endif | 215 #endif |
| 216 | 216 |
| 217 SysTime seconds = SysTimeFromTimeStruct(×truct, is_local); | |
| 218 | 217 |
| 219 int64 milliseconds; | 218 int64 milliseconds; |
| 219 SysTime seconds; | |
| 220 | |
| 221 // On older releases of Android, mktime() will sometimes return -1 when given | |
| 222 // any second after midnight in certain timezones. For more details, see: | |
| 223 // http://b.android.com/61137 | |
| 224 #if defined(OS_ANDROID) | |
| 225 // SysTimeFromTimeStruct() modifies the input structure, save current value. | |
| 226 struct tm timestruct0 = timestruct; | |
| 227 | |
| 228 seconds = SysTimeFromTimeStruct(×truct, is_local); | |
| 229 if (seconds == -1 && exploded.hour == 0) { | |
| 230 // Work-around this by trying to add one hour. | |
| 231 timestruct0.tm_hour = 1; | |
| 232 seconds = SysTimeFromTimeStruct(×truct0, is_local); | |
| 233 if (seconds != -1) | |
| 234 seconds -= 60 * 60; | |
| 235 } | |
| 236 #else | |
| 237 seconds = SysTimeFromTimeStruct(×truct, is_local); | |
| 238 #endif | |
| 239 | |
| 220 // Handle overflow. Clamping the range to what mktime and timegm might | 240 // Handle overflow. Clamping the range to what mktime and timegm might |
| 221 // return is the best that can be done here. It's not ideal, but it's better | 241 // return is the best that can be done here. It's not ideal, but it's better |
| 222 // than failing here or ignoring the overflow case and treating each time | 242 // than failing here or ignoring the overflow case and treating each time |
| 223 // overflow as one second prior to the epoch. | 243 // overflow as one second prior to the epoch. |
| 224 if (seconds == -1 && | 244 if (seconds == -1 && |
| 225 (exploded.year < 1969 || exploded.year > 1970)) { | 245 (exploded.year < 1969 || exploded.year > 1970)) { |
| 226 // If exploded.year is 1969 or 1970, take -1 as correct, with the | 246 // If exploded.year is 1969 or 1970, take -1 as correct, with the |
| 227 // time indicating 1 second prior to the epoch. (1970 is allowed to handle | 247 // time indicating 1 second prior to the epoch. (1970 is allowed to handle |
| 228 // time zone and DST offsets.) Otherwise, return the most future or past | 248 // time zone and DST offsets.) Otherwise, return the most future or past |
| 229 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. | 249 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. |
| 230 // | 250 // |
| 231 // The minimum and maximum representible times that mktime and timegm could | 251 // The minimum and maximum representible times that mktime and timegm could |
| 232 // return are used here instead of values outside that range to allow for | 252 // return are used here instead of values outside that range to allow for |
| 233 // proper round-tripping between exploded and counter-type time | 253 // proper round-tripping between exploded and counter-type time |
| 234 // representations in the presence of possible truncation to time_t by | 254 // representations in the presence of possible truncation to time_t by |
| 235 // division and use with other functions that accept time_t. | 255 // division and use with other functions that accept time_t. |
| 236 // | 256 // |
| 237 // When representing the most distant time in the future, add in an extra | 257 // When representing the most distant time in the future, add in an extra |
| 238 // 999ms to avoid the time being less than any other possible value that | 258 // 999ms to avoid the time being less than any other possible value that |
| 239 // this function can return. | 259 // this function can return. |
| 260 | |
| 261 // On Android, SysTime is int64, special care must be taken to avoid | |
| 262 // overflows. | |
| 263 const int64 min_seconds = (sizeof(SysTime) < sizeof(int64)) | |
| 264 ? std::numeric_limits<SysTime>::min() | |
| 265 : std::numeric_limits<int32_t>::min(); | |
|
digit1
2013/10/17 14:00:27
I'm still not sure that using INT32_MAX here is su
| |
| 266 const int64 max_seconds = (sizeof(SysTime) < sizeof(int64)) | |
| 267 ? std::numeric_limits<SysTime>::max() | |
| 268 : std::numeric_limits<int32_t>::max(); | |
| 240 if (exploded.year < 1969) { | 269 if (exploded.year < 1969) { |
| 241 CHECK(sizeof(SysTime) < sizeof(int64)) << "integer overflow"; | 270 milliseconds = min_seconds * kMillisecondsPerSecond; |
| 242 milliseconds = std::numeric_limits<SysTime>::min(); | |
| 243 milliseconds *= kMillisecondsPerSecond; | |
| 244 } else { | 271 } else { |
| 245 CHECK(sizeof(SysTime) < sizeof(int64)) << "integer overflow"; | 272 milliseconds = max_seconds * kMillisecondsPerSecond; |
| 246 milliseconds = std::numeric_limits<SysTime>::max(); | |
| 247 milliseconds *= kMillisecondsPerSecond; | |
| 248 milliseconds += (kMillisecondsPerSecond - 1); | 273 milliseconds += (kMillisecondsPerSecond - 1); |
| 249 } | 274 } |
| 250 } else { | 275 } else { |
| 251 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; | 276 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; |
| 252 } | 277 } |
| 253 | 278 |
| 254 // Adjust from Unix (1970) to Windows (1601) epoch. | 279 // Adjust from Unix (1970) to Windows (1601) epoch. |
| 255 return Time((milliseconds * kMicrosecondsPerMillisecond) + | 280 return Time((milliseconds * kMicrosecondsPerMillisecond) + |
| 256 kWindowsEpochDeltaMicroseconds); | 281 kWindowsEpochDeltaMicroseconds); |
| 257 } | 282 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 343 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; | 368 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; |
| 344 return result; | 369 return result; |
| 345 } | 370 } |
| 346 int64 us = us_ - kTimeTToMicrosecondsOffset; | 371 int64 us = us_ - kTimeTToMicrosecondsOffset; |
| 347 result.tv_sec = us / Time::kMicrosecondsPerSecond; | 372 result.tv_sec = us / Time::kMicrosecondsPerSecond; |
| 348 result.tv_usec = us % Time::kMicrosecondsPerSecond; | 373 result.tv_usec = us % Time::kMicrosecondsPerSecond; |
| 349 return result; | 374 return result; |
| 350 } | 375 } |
| 351 | 376 |
| 352 } // namespace base | 377 } // namespace base |
| OLD | NEW |