Fix incorrect unsigned math in pr_time.cc on Windows which incorrectly handled times before 1970 Epoch.
Improved Linux's handling of timegm() failure. Adding more test cases at / around Epoch. BUG=1327608 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@982 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
base
@ -181,3 +181,79 @@ TEST_F(PRTimeTest, ParseTimeTest11) {
|
||||
time_t time_to_compare = comparison_time_pdt / Time::kMicrosecondsPerSecond;
|
||||
EXPECT_EQ(computed_time, time_to_compare);
|
||||
}
|
||||
|
||||
// Test some of edge cases around epoch, etc.
|
||||
TEST_F(PRTimeTest, ParseTimeTestEpoch0) {
|
||||
Time parsed_time;
|
||||
|
||||
// time_t == epoch == 0
|
||||
EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 01:00:00 +0100 1970",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(0, parsed_time.ToTimeT());
|
||||
EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 00:00:00 GMT 1970",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(0, parsed_time.ToTimeT());
|
||||
}
|
||||
|
||||
TEST_F(PRTimeTest, ParseTimeTestEpoch1) {
|
||||
Time parsed_time;
|
||||
|
||||
// time_t == 1 second after epoch == 1
|
||||
EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 01:00:01 +0100 1970",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(1, parsed_time.ToTimeT());
|
||||
EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 00:00:01 GMT 1970",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(1, parsed_time.ToTimeT());
|
||||
}
|
||||
|
||||
TEST_F(PRTimeTest, ParseTimeTestEpoch2) {
|
||||
Time parsed_time;
|
||||
|
||||
// time_t == 2 seconds after epoch == 2
|
||||
EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 01:00:02 +0100 1970",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(2, parsed_time.ToTimeT());
|
||||
EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 00:00:02 GMT 1970",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(2, parsed_time.ToTimeT());
|
||||
}
|
||||
|
||||
TEST_F(PRTimeTest, ParseTimeTestEpochNeg1) {
|
||||
Time parsed_time;
|
||||
|
||||
// time_t == 1 second before epoch == -1
|
||||
EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 00:59:59 +0100 1970",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(-1, parsed_time.ToTimeT());
|
||||
EXPECT_EQ(true, Time::FromString(L"Wed Dec 31 23:59:59 GMT 1969",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(-1, parsed_time.ToTimeT());
|
||||
}
|
||||
|
||||
TEST_F(PRTimeTest, ParseTimeTestEpochNeg2) {
|
||||
Time parsed_time;
|
||||
|
||||
// time_t == 2 seconds before epoch == -2
|
||||
EXPECT_EQ(true, Time::FromString(L"Thu Jan 01 00:59:58 +0100 1970",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(-2, parsed_time.ToTimeT());
|
||||
EXPECT_EQ(true, Time::FromString(L"Wed Dec 31 23:59:58 GMT 1969",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(-2, parsed_time.ToTimeT());
|
||||
}
|
||||
|
||||
TEST_F(PRTimeTest, ParseTimeTestEpoch1960) {
|
||||
Time parsed_time;
|
||||
|
||||
// time_t before Epoch, in 1960
|
||||
EXPECT_EQ(true, Time::FromString(L"Wed Jun 29 19:40:01 +0100 1960",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(-299999999, parsed_time.ToTimeT());
|
||||
EXPECT_EQ(true, Time::FromString(L"Wed Jun 29 18:40:01 GMT 1960",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(-299999999, parsed_time.ToTimeT());
|
||||
EXPECT_EQ(true, Time::FromString(L"Wed Jun 29 17:40:01 GMT 1960",
|
||||
&parsed_time));
|
||||
EXPECT_EQ(-300003599, parsed_time.ToTimeT());
|
||||
}
|
||||
|
39
base/third_party/nspr/prtime.cc
vendored
39
base/third_party/nspr/prtime.cc
vendored
@ -92,6 +92,9 @@ static void localtime_r(const time_t* secs, struct tm* time) {
|
||||
PRTime
|
||||
PR_ImplodeTime(const PRExplodedTime *exploded)
|
||||
{
|
||||
// This is important, we want to make sure multiplications are
|
||||
// done with the correct precision.
|
||||
static const PRTime kSecondsToMicroseconds = static_cast<PRTime>(1000000);
|
||||
#if defined(OS_WIN)
|
||||
// Create the system struct representing our exploded time.
|
||||
SYSTEMTIME st = {0};
|
||||
@ -114,14 +117,14 @@ PR_ImplodeTime(const PRExplodedTime *exploded)
|
||||
// Apply offsets.
|
||||
uli.LowPart = ft.dwLowDateTime;
|
||||
uli.HighPart = ft.dwHighDateTime;
|
||||
// From second to 100-ns
|
||||
uli.QuadPart -=
|
||||
(exploded->tm_params.tp_gmt_offset +
|
||||
exploded->tm_params.tp_dst_offset) * 10000000i64; // 7 zeros
|
||||
// Convert to PRTime
|
||||
uli.QuadPart -= 116444736000000000i64; // from Windows epoch to NSPR epoch
|
||||
uli.QuadPart /= 10; // from 100-nanosecond to microsecond
|
||||
return (PRTime)uli.QuadPart;
|
||||
// Convert from Windows epoch to NSPR epoch, and 100-nanoseconds units
|
||||
// to microsecond units.
|
||||
PRTime result =
|
||||
static_cast<PRTime>((uli.QuadPart / 10) - 11644473600000000i64);
|
||||
// Adjust for time zone and dst. Convert from seconds to microseconds.
|
||||
result -= (exploded->tm_params.tp_gmt_offset +
|
||||
exploded->tm_params.tp_dst_offset) * kSecondsToMicroseconds;
|
||||
return result;
|
||||
#elif defined(OS_MACOSX)
|
||||
// Create the system struct representing our exploded time.
|
||||
CFGregorianDate gregorian_date;
|
||||
@ -141,7 +144,7 @@ PR_ImplodeTime(const PRExplodedTime *exploded)
|
||||
result -= exploded->tm_params.tp_gmt_offset +
|
||||
exploded->tm_params.tp_dst_offset;
|
||||
result += kCFAbsoluteTimeIntervalSince1970; // PRTime epoch is 1970
|
||||
result *= 1000000L; // Seconds to microseconds
|
||||
result *= kSecondsToMicroseconds;
|
||||
result += exploded->tm_usec;
|
||||
return result;
|
||||
#elif defined(OS_LINUX)
|
||||
@ -156,23 +159,25 @@ PR_ImplodeTime(const PRExplodedTime *exploded)
|
||||
// We assume that time_t is defined as a long.
|
||||
time_t absolute_time = timegm(&exp_tm);
|
||||
|
||||
if (absolute_time == -1) {
|
||||
// If timegm returned -1. Since we don't pass it a time zone, the only
|
||||
// valid case of returning -1 is 1 second before Epoch (Dec 31, 1969).
|
||||
if (absolute_time == -1 &&
|
||||
exploded->tm_year != 1969 && exploded->tm_month != 11 &&
|
||||
exploded->tm_mday != 31 && exploded->tm_hour != 23 &&
|
||||
exploded->tm_min != 59 && exploded->tm_sec != 59) {
|
||||
// Date was possibly too far in the future and would overflow. Return
|
||||
// the most future date possible (year 2038).
|
||||
if (exploded->tm_year > 1970)
|
||||
return static_cast<PRTime>(LONG_MAX) * 1000000;
|
||||
if (exploded->tm_year >= 1970)
|
||||
return static_cast<PRTime>(LONG_MAX) * kSecondsToMicroseconds;
|
||||
// Date was possibly too far in the past and would underflow. Return
|
||||
// the most past date possible (year 1901).
|
||||
if (exploded->tm_year < 1969)
|
||||
return static_cast<PRTime>(LONG_MIN) * 1000000;
|
||||
// Year was 1969 or 1970, assume -1 was the correct conversion.
|
||||
return static_cast<PRTime>(-1) * 1000000;
|
||||
return static_cast<PRTime>(LONG_MIN) * kSecondsToMicroseconds;
|
||||
}
|
||||
|
||||
PRTime result = static_cast<PRTime>(absolute_time);
|
||||
result -= exploded->tm_params.tp_gmt_offset +
|
||||
exploded->tm_params.tp_dst_offset;
|
||||
result *= 1000000L; // Seconds to microseconds
|
||||
result *= kSecondsToMicroseconds;
|
||||
result += exploded->tm_usec;
|
||||
return result;
|
||||
#else
|
||||
|
Reference in New Issue
Block a user