Commit 29296d7e authored by ulan@chromium.org's avatar ulan@chromium.org

Fix computation of UTC time from local time at DST change points.

This also reverts r23606, which was an incorrect fix.

BUG=v8:3116,chromium:417640,chromium:415424
LOG=Y
TEST=mjsunit/regress/regress-3116.js
R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/639383002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24499 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e604df03
...@@ -104,21 +104,51 @@ class DateCache { ...@@ -104,21 +104,51 @@ class DateCache {
// ECMA 262 - 15.9.1.9 // ECMA 262 - 15.9.1.9
// LocalTime(t) = t + LocalTZA + DaylightSavingTA(t) // LocalTime(t) = t + LocalTZA + DaylightSavingTA(t)
// ECMA 262 assumes that DaylightSavingTA is computed using UTC time,
// but we fetch DST from OS using local time, therefore we need:
// LocalTime(t) = t + LocalTZA + DaylightSavingTA(t + LocalTZA).
int64_t ToLocal(int64_t time_ms) { int64_t ToLocal(int64_t time_ms) {
time_ms += LocalOffsetInMs(); return time_ms + LocalOffsetInMs() + DaylightSavingsOffsetInMs(time_ms);
return time_ms + DaylightSavingsOffsetInMs(time_ms);
} }
// ECMA 262 - 15.9.1.9 // ECMA 262 - 15.9.1.9
// UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA) // UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
// ECMA 262 assumes that DaylightSavingTA is computed using UTC time,
// but we fetch DST from OS using local time, therefore we need:
// UTC(t) = t - LocalTZA - DaylightSavingTA(t).
int64_t ToUTC(int64_t time_ms) { int64_t ToUTC(int64_t time_ms) {
return time_ms - LocalOffsetInMs() - DaylightSavingsOffsetInMs(time_ms); // We need to compute UTC time that corresponds to the given local time.
// Literally following spec here leads to incorrect time computation at
// the points were we transition to and from DST.
//
// The following shows that using DST for (t - LocalTZA - hour) produces
// correct conversion.
//
// Consider transition to DST at local time L1.
// Let L0 = L1 - hour, L2 = L1 + hour,
// U1 = UTC time that corresponds to L1,
// U0 = U1 - hour.
// Transitioning to DST moves local clock one hour forward L1 => L2, so
// U0 = UTC time that corresponds to L0 = L0 - LocalTZA,
// U1 = UTC time that corresponds to L1 = L1 - LocalTZA,
// U1 = UTC time that corresponds to L2 = L2 - LocalTZA - hour.
// Note that DST(U0 - hour) = 0, DST(U0) = 0, DST(U1) = 1.
// U0 = L0 - LocalTZA - DST(L0 - LocalTZA - hour),
// U1 = L1 - LocalTZA - DST(L1 - LocalTZA - hour),
// U1 = L2 - LocalTZA - DST(L2 - LocalTZA - hour).
//
// Consider transition from DST at local time L1.
// Let L0 = L1 - hour,
// U1 = UTC time that corresponds to L1,
// U0 = U1 - hour, U2 = U1 + hour.
// Transitioning from DST moves local clock one hour back L1 => L0, so
// U0 = UTC time that corresponds to L0 (before transition)
// = L0 - LocalTZA - hour.
// U1 = UTC time that corresponds to L0 (after transition)
// = L0 - LocalTZA = L1 - LocalTZA - hour
// U2 = UTC time that corresponds to L1 = L1 - LocalTZA.
// Note that DST(U0) = 1, DST(U1) = 0, DST(U2) = 0.
// U0 = L0 - LocalTZA - DST(L0 - LocalTZA - hour) = L0 - LocalTZA - DST(U0).
// U2 = L1 - LocalTZA - DST(L1 - LocalTZA - hour) = L1 - LocalTZA - DST(U1).
// It is impossible to get U1 from local time.
const int kMsPerHour = 3600 * 1000;
time_ms -= LocalOffsetInMs();
return time_ms - DaylightSavingsOffsetInMs(time_ms - kMsPerHour);
} }
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment