Index: base/time_posix.cc |
diff --git a/base/time_posix.cc b/base/time_posix.cc |
index 8b295bdc61af555a773c61b009a592b5c492d4d1..ccfbca5fbd17c7dce7b7630400218c9535db7cb5 100644 |
--- a/base/time_posix.cc |
+++ b/base/time_posix.cc |
@@ -6,6 +6,9 @@ |
#include <sys/time.h> |
#include <time.h> |
+#if defined(OS_ANDROID) |
+#include <time64.h> |
+#endif |
#include <unistd.h> |
#include <limits> |
@@ -88,6 +91,54 @@ Time Time::NowFromSystemTime() { |
return Now(); |
} |
+// 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.
|
+// a time64_t depending on the host system. See crbug.com/162007 |
+#if defined(OS_ANDROID) |
+struct SysTimeT { |
digit1
2012/11/29 13:49:30
A small comment here: I'm not really sure that a n
|
+ typedef time64_t type; |
+ |
+ SysTimeT() : t(0) {} |
+ |
+ explicit SysTimeT(struct tm* timestruct, bool is_local) { |
+ if (is_local) |
+ t = mktime64(timestruct); |
+ else |
+ t = timegm64(timestruct); |
+ } |
+ |
+ void ToTimeStruct(struct tm* timestruct, bool is_local) { |
+ if (is_local) |
+ localtime64_r(&t, timestruct); |
+ else |
+ gmtime64_r(&t, timestruct); |
+ } |
+ |
+ time64_t t; |
+}; |
+#else |
+struct SysTimeT { |
+ typedef time_t type; |
+ |
+ SysTimeT() : t(0) {} |
+ |
+ explicit SysTimeT(struct tm* timestruct, bool is_local) { |
+ if (is_local) |
+ t = mktime(timestruct); |
+ else |
+ t = timegm(timestruct); |
+ } |
+ |
+ void ToTimeStruct(struct tm* timestruct, bool is_local) { |
+ if (is_local) |
+ localtime_r(&t, timestruct); |
+ else |
+ gmtime_r(&t, timestruct); |
+ } |
+ |
+ time_t t; |
+}; |
+#endif |
+ |
void Time::Explode(bool is_local, Exploded* exploded) const { |
// Time stores times with microsecond resolution, but Exploded only carries |
// millisecond resolution, so begin by being lossy. Adjust from Windows |
@@ -95,19 +146,19 @@ void Time::Explode(bool is_local, Exploded* exploded) const { |
int64 microseconds = us_ - kWindowsEpochDeltaMicroseconds; |
// The following values are all rounded towards -infinity. |
int64 milliseconds; // Milliseconds since epoch. |
- time_t seconds; // Seconds since epoch. |
+ SysTimeT seconds; // Seconds since epoch. |
int millisecond; // Exploded millisecond value (0-999). |
if (microseconds >= 0) { |
// Rounding towards -infinity <=> rounding towards 0, in this case. |
milliseconds = microseconds / kMicrosecondsPerMillisecond; |
- seconds = milliseconds / kMillisecondsPerSecond; |
+ seconds.t = milliseconds / kMillisecondsPerSecond; |
millisecond = milliseconds % kMillisecondsPerSecond; |
} else { |
// Round these *down* (towards -infinity). |
milliseconds = (microseconds - kMicrosecondsPerMillisecond + 1) / |
kMicrosecondsPerMillisecond; |
- seconds = (milliseconds - kMillisecondsPerSecond + 1) / |
- kMillisecondsPerSecond; |
+ seconds.t = (milliseconds - kMillisecondsPerSecond + 1) / |
+ kMillisecondsPerSecond; |
// Make this nonnegative (and between 0 and 999 inclusive). |
millisecond = milliseconds % kMillisecondsPerSecond; |
if (millisecond < 0) |
@@ -115,10 +166,7 @@ void Time::Explode(bool is_local, Exploded* exploded) const { |
} |
struct tm timestruct; |
- if (is_local) |
- localtime_r(&seconds, ×truct); |
- else |
- gmtime_r(&seconds, ×truct); |
+ seconds.ToTimeStruct(×truct, is_local); |
exploded->year = timestruct.tm_year + 1900; |
exploded->month = timestruct.tm_mon + 1; |
@@ -147,18 +195,14 @@ Time Time::FromExploded(bool is_local, const Exploded& exploded) { |
timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore |
#endif |
- time_t seconds; |
- if (is_local) |
- seconds = mktime(×truct); |
- else |
- seconds = timegm(×truct); |
+ SysTimeT seconds(×truct, is_local); |
int64 milliseconds; |
// 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 |
// overflow as one second prior to the epoch. |
- if (seconds == -1 && |
+ if (seconds.t == -1 && |
(exploded.year < 1969 || exploded.year > 1970)) { |
// If exploded.year is 1969 or 1970, take -1 as correct, with the |
// time indicating 1 second prior to the epoch. (1970 is allowed to handle |
@@ -175,15 +219,15 @@ Time Time::FromExploded(bool is_local, const Exploded& exploded) { |
// 999ms to avoid the time being less than any other possible value that |
// this function can return. |
if (exploded.year < 1969) { |
- milliseconds = std::numeric_limits<time_t>::min() * |
+ milliseconds = std::numeric_limits<SysTimeT::type>::min() * |
kMillisecondsPerSecond; |
} else { |
- milliseconds = (std::numeric_limits<time_t>::max() * |
+ milliseconds = (std::numeric_limits<SysTimeT::type>::max() * |
kMillisecondsPerSecond) + |
kMillisecondsPerSecond - 1; |
} |
} else { |
- milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; |
+ milliseconds = seconds.t * kMillisecondsPerSecond + exploded.millisecond; |
} |
// Adjust from Unix (1970) to Windows (1601) epoch. |