| Index: base/time/time_posix.cc
|
| ===================================================================
|
| --- base/time/time_posix.cc (revision 229821)
|
| +++ base/time/time_posix.cc (working copy)
|
| @@ -211,9 +211,41 @@
|
| timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore
|
| #endif
|
|
|
| - SysTime seconds = SysTimeFromTimeStruct(×truct, is_local);
|
|
|
| int64 milliseconds;
|
| + SysTime seconds;
|
| +
|
| + // Certain exploded dates do not really exist due to daylight saving times,
|
| + // and this causes mktime() to return implementation-defined values when
|
| + // tm_isdst is set to -1. On Android, the function will return -1, while the
|
| + // C libraries of other platforms typically return a liberally-chosen value.
|
| + // Handling this requires the special code below.
|
| +
|
| + // SysTimeFromTimeStruct() modifies the input structure, save current value.
|
| + struct tm timestruct0 = timestruct;
|
| +
|
| + seconds = SysTimeFromTimeStruct(×truct, is_local);
|
| + if (seconds == -1) {
|
| + // Get the time values with tm_isdst == 0 and 1, then select the closest one
|
| + // to UTC 00:00:00 that isn't -1.
|
| + timestruct = timestruct0;
|
| + timestruct.tm_isdst = 0;
|
| + int64 seconds_isdst0 = SysTimeFromTimeStruct(×truct, is_local);
|
| +
|
| + timestruct = timestruct0;
|
| + timestruct.tm_isdst = 1;
|
| + int64 seconds_isdst1 = SysTimeFromTimeStruct(×truct, is_local);
|
| +
|
| + // seconds_isdst0 or seconds_isdst1 can be -1 for some timezones.
|
| + // E.g. "CLST" (Chile Summer Time) returns -1 for 'tm_isdt == 1'.
|
| + if (seconds_isdst0 < 0)
|
| + seconds = seconds_isdst1;
|
| + else if (seconds_isdst1 < 0)
|
| + seconds = seconds_isdst0;
|
| + else
|
| + seconds = std::min(seconds_isdst0, seconds_isdst1);
|
| + }
|
| +
|
| // Handle overflow. Clamping the range to what mktime and timegm might
|
| // return is the best that can be done here. It's not ideal, but it's better
|
| // than failing here or ignoring the overflow case and treating each time
|
| @@ -234,14 +266,19 @@
|
| // When representing the most distant time in the future, add in an extra
|
| // 999ms to avoid the time being less than any other possible value that
|
| // this function can return.
|
| +
|
| + // On Android, SysTime is int64, special care must be taken to avoid
|
| + // overflows.
|
| + const int64 min_seconds = (sizeof(SysTime) < sizeof(int64))
|
| + ? std::numeric_limits<SysTime>::min()
|
| + : std::numeric_limits<int32_t>::min();
|
| + const int64 max_seconds = (sizeof(SysTime) < sizeof(int64))
|
| + ? std::numeric_limits<SysTime>::max()
|
| + : std::numeric_limits<int32_t>::max();
|
| if (exploded.year < 1969) {
|
| - CHECK(sizeof(SysTime) < sizeof(int64)) << "integer overflow";
|
| - milliseconds = std::numeric_limits<SysTime>::min();
|
| - milliseconds *= kMillisecondsPerSecond;
|
| + milliseconds = min_seconds * kMillisecondsPerSecond;
|
| } else {
|
| - CHECK(sizeof(SysTime) < sizeof(int64)) << "integer overflow";
|
| - milliseconds = std::numeric_limits<SysTime>::max();
|
| - milliseconds *= kMillisecondsPerSecond;
|
| + milliseconds = max_seconds * kMillisecondsPerSecond;
|
| milliseconds += (kMillisecondsPerSecond - 1);
|
| }
|
| } else {
|
|
|