Skip to content
Permalink
Browse files
String(new Date(Mar 30 2014 01:00:00)) is wrong in CET
https://bugs.webkit.org/show_bug.cgi?id=130967

Patch by Byungseon Shin <sun.shin@lge.com> on 2014-10-22
Reviewed by Mark Lam.

Source/JavaScriptCore:

By definition of calculateLocalTimeOffset, input time should be UTC time.
But there are many cases when input time is based on local time.
So, it gives erroneous results while calculating offset of DST boundary time.
By adding a argument to distinguish UTC and local time, we can get the correct offset.

* JavaScriptCore.order:
* runtime/DateConstructor.cpp:
(JSC::constructDate):
(JSC::callDate):
(JSC::dateUTC):
* runtime/DateInstance.cpp:
(JSC::DateInstance::calculateGregorianDateTime):
(JSC::DateInstance::calculateGregorianDateTimeUTC):
* runtime/DatePrototype.cpp:
(JSC::setNewValueFromTimeArgs):
(JSC::setNewValueFromDateArgs):
(JSC::dateProtoFuncSetMilliSeconds):
(JSC::dateProtoFuncSetUTCMilliseconds):
(JSC::dateProtoFuncSetSeconds):
(JSC::dateProtoFuncSetUTCSeconds):
(JSC::dateProtoFuncSetMinutes):
(JSC::dateProtoFuncSetUTCMinutes):
(JSC::dateProtoFuncSetHours):
(JSC::dateProtoFuncSetUTCHours):
(JSC::dateProtoFuncSetDate):
(JSC::dateProtoFuncSetUTCDate):
(JSC::dateProtoFuncSetMonth):
(JSC::dateProtoFuncSetUTCMonth):
(JSC::dateProtoFuncSetFullYear):
(JSC::dateProtoFuncSetUTCFullYear):
(JSC::dateProtoFuncSetYear):
* runtime/JSDateMath.cpp:
(JSC::localTimeOffset):
(JSC::gregorianDateTimeToMS):
(JSC::msToGregorianDateTime):
(JSC::parseDateFromNullTerminatedCharacters):
* runtime/JSDateMath.h:
* runtime/VM.h:
(JSC::LocalTimeOffsetCache::LocalTimeOffsetCache):
(JSC::LocalTimeOffsetCache::reset):
Passing TimeType argument to distingush UTC time and local time.

Source/WTF:

By definition of calculateLocalTimeOffset, input time should be UTC time.
But there are many cases when input time is based on local time.
So, it gives erroneous results while calculating offset of DST boundary time.
By adding a argument to distinguish UTC and local time, we can get the correct offset.

* wtf/DateMath.cpp:
(WTF::calculateLocalTimeOffset):
(WTF::parseDateFromNullTerminatedCharacters):
Compensate time offset depends on UTC time or local time.
* wtf/DateMath.h:
Add argument to differenciate UTC or local time.

LayoutTests:

Set latest DST timezone boundary values on
<http://www.timeanddate.com/time/zone/usa/los-angeles>

* js/dom/script-tests/date-DST-time-cusps.js:

Canonical link: https://commits.webkit.org/155847@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@175078 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
xingri authored and webkit-commit-queue committed Oct 23, 2014
1 parent 253a59f commit 1fc68a1b45d38340c62179385cee82a635d708f7
Showing 13 changed files with 171 additions and 77 deletions.
@@ -1,3 +1,15 @@
2014-10-22 Byungseon Shin <sun.shin@lge.com>

String(new Date(Mar 30 2014 01:00:00)) is wrong in CET
https://bugs.webkit.org/show_bug.cgi?id=130967

Reviewed by Mark Lam.

Set latest DST timezone boundary values on
<http://www.timeanddate.com/time/zone/usa/los-angeles>

* js/dom/script-tests/date-DST-time-cusps.js:

2014-10-22 Brent Fulgham <bfulgham@apple.com>

[Win] Rebaseline various tests after switching to Windows rendering for native controls.
@@ -7,11 +7,11 @@ description(
);

var testCases = [];
if ((new Date(2009, 9, 1)).toString().match("PDT")) {
testCases.push(["(new Date(1982, 2, 14, 2, 10)).getHours()", "3"]);
testCases.push(["(new Date(1982, 2, 14, 2)).getHours()", "3"]);
testCases.push(["(new Date(1982, 11, 7, 1, 10)).getTimezoneOffset()", "480"]);
testCases.push(["(new Date(1982, 11, 7, 1)).getTimezoneOffset()", "480"]);
if ((new Date(2014, 8, 1)).toString().match("PDT")) {
testCases.push(["(new Date('Mar 09 2014 03:00:00')).getHours()", "3"]);
testCases.push(["(new Date('Mar 09 2014 03:00:00')).getTimezoneOffset()", "420"]);
testCases.push(["(new Date('Nov 02 2014 01:00:00')).getHours()", "1"]);
testCases.push(["(new Date('Nov 02 2014 01:00:00')).getTimezoneOffset()", "480"]);
}

var errors = [];
@@ -1,3 +1,52 @@
2014-10-22 Byungseon Shin <sun.shin@lge.com>

String(new Date(Mar 30 2014 01:00:00)) is wrong in CET
https://bugs.webkit.org/show_bug.cgi?id=130967

Reviewed by Mark Lam.

By definition of calculateLocalTimeOffset, input time should be UTC time.
But there are many cases when input time is based on local time.
So, it gives erroneous results while calculating offset of DST boundary time.
By adding a argument to distinguish UTC and local time, we can get the correct offset.

* JavaScriptCore.order:
* runtime/DateConstructor.cpp:
(JSC::constructDate):
(JSC::callDate):
(JSC::dateUTC):
* runtime/DateInstance.cpp:
(JSC::DateInstance::calculateGregorianDateTime):
(JSC::DateInstance::calculateGregorianDateTimeUTC):
* runtime/DatePrototype.cpp:
(JSC::setNewValueFromTimeArgs):
(JSC::setNewValueFromDateArgs):
(JSC::dateProtoFuncSetMilliSeconds):
(JSC::dateProtoFuncSetUTCMilliseconds):
(JSC::dateProtoFuncSetSeconds):
(JSC::dateProtoFuncSetUTCSeconds):
(JSC::dateProtoFuncSetMinutes):
(JSC::dateProtoFuncSetUTCMinutes):
(JSC::dateProtoFuncSetHours):
(JSC::dateProtoFuncSetUTCHours):
(JSC::dateProtoFuncSetDate):
(JSC::dateProtoFuncSetUTCDate):
(JSC::dateProtoFuncSetMonth):
(JSC::dateProtoFuncSetUTCMonth):
(JSC::dateProtoFuncSetFullYear):
(JSC::dateProtoFuncSetUTCFullYear):
(JSC::dateProtoFuncSetYear):
* runtime/JSDateMath.cpp:
(JSC::localTimeOffset):
(JSC::gregorianDateTimeToMS):
(JSC::msToGregorianDateTime):
(JSC::parseDateFromNullTerminatedCharacters):
* runtime/JSDateMath.h:
* runtime/VM.h:
(JSC::LocalTimeOffsetCache::LocalTimeOffsetCache):
(JSC::LocalTimeOffsetCache::reset):
Passing TimeType argument to distingush UTC time and local time.

2014-10-22 Joseph Pecoraro <pecoraro@apple.com>

Web Inspector: Fix generator importing of protocol type "any", treat as value
@@ -3196,7 +3196,6 @@ __ZN3JSCL24dateProtoFuncToGMTStringEPNS_9ExecStateE
__ZN3JSCL19formateDateInstanceEPNS_9ExecStateENS_14DateTimeFormatEb
__ZNK3JSC12DateInstance29calculateGregorianDateTimeUTCEPNS_9ExecStateE
__ZN3JSC17DateInstanceCache3addEd
__ZN3JSC21msToGregorianDateTimeEPNS_9ExecStateEdbRN3WTF17GregorianDateTimeE
__ZN3WTF8msToYearEd
__ZN3WTF11msToMinutesEd
__ZN3WTF9msToHoursEd
@@ -3272,7 +3271,6 @@ __ZN3JSC3JIT21emitLoadInt32ToDoubleEiNS_12X86Registers13XMMRegisterIDE
__ZN3JSC14MacroAssembler20convertInt32ToDoubleENS_22AbstractMacroAssemblerINS_12X86AssemblerEE5Imm32ENS_12X86Registers13XMMRegisterIDE
__ZN3JSC3JIT15emitSlow_op_modEPNS_11InstructionERPNS_13SlowCaseEntryE
__ZN3JSCL20dateProtoFuncSetYearEPNS_9ExecStateE
__ZN3JSC21gregorianDateTimeToMSEPNS_9ExecStateERKN3WTF17GregorianDateTimeEdb
__ZN3WTF18dateToDaysFrom1970Eiii
__ZN3JSC10PrefixNode11emitBracketERNS_17BytecodeGeneratorEPNS_10RegisterIDE
__ZN3JSC16globalFuncEscapeEPNS_9ExecStateE
@@ -162,7 +162,7 @@ JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const Arg
t.setSecond(JSC::toInt32(doubleArguments[5]));
t.setIsDST(-1);
double ms = (numArgs >= 7) ? doubleArguments[6] : 0;
value = gregorianDateTimeToMS(vm, t, ms, false);
value = gregorianDateTimeToMS(vm, t, ms, WTF::LocalTime);
}
}

@@ -186,7 +186,7 @@ static EncodedJSValue JSC_HOST_CALL callDate(ExecState* exec)
{
VM& vm = exec->vm();
GregorianDateTime ts;
msToGregorianDateTime(vm, currentTimeMS(), false, ts);
msToGregorianDateTime(vm, currentTimeMS(), WTF::LocalTime, ts);
return JSValue::encode(jsNontrivialString(&vm, formatDateTime(ts, DateTimeFormatDateAndTime, false)));
}

@@ -240,7 +240,7 @@ EncodedJSValue JSC_HOST_CALL dateUTC(ExecState* exec)
t.setMinute(JSC::toInt32(doubleArguments[4]));
t.setSecond(JSC::toInt32(doubleArguments[5]));
double ms = (n >= 7) ? doubleArguments[6] : 0;
return JSValue::encode(jsNumber(timeClip(gregorianDateTimeToMS(exec->vm(), t, ms, true))));
return JSValue::encode(jsNumber(timeClip(gregorianDateTimeToMS(exec->vm(), t, ms, WTF::UTCTime))));
}

} // namespace JSC
@@ -69,7 +69,7 @@ const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exe
m_data = vm.dateInstanceCache.add(milli);

if (m_data->m_gregorianDateTimeCachedForMS != milli) {
msToGregorianDateTime(vm, milli, false, m_data->m_cachedGregorianDateTime);
msToGregorianDateTime(vm, milli, WTF::LocalTime, m_data->m_cachedGregorianDateTime);
m_data->m_gregorianDateTimeCachedForMS = milli;
}
return &m_data->m_cachedGregorianDateTime;
@@ -86,7 +86,7 @@ const GregorianDateTime* DateInstance::calculateGregorianDateTimeUTC(ExecState*
m_data = vm.dateInstanceCache.add(milli);

if (m_data->m_gregorianDateTimeUTCCachedForMS != milli) {
msToGregorianDateTime(vm, milli, true, m_data->m_cachedGregorianDateTimeUTC);
msToGregorianDateTime(vm, milli, WTF::UTCTime, m_data->m_cachedGregorianDateTimeUTC);
m_data->m_gregorianDateTimeUTCCachedForMS = milli;
}
return &m_data->m_cachedGregorianDateTimeUTC;
@@ -859,7 +859,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec)
return JSValue::encode(result);
}

static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC)
static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, WTF::TimeType inputTimeType)
{
JSValue thisValue = exec->thisValue();
if (!thisValue.inherits(DateInstance::info()))
@@ -878,7 +878,7 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse,
double secs = floor(milli / msPerSecond);
double ms = milli - secs * msPerSecond;

const GregorianDateTime* other = inputIsUTC
const GregorianDateTime* other = inputTimeType == WTF::UTCTime
? thisDateObj->gregorianDateTimeUTC(exec)
: thisDateObj->gregorianDateTime(exec);
if (!other)
@@ -892,12 +892,12 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse,
return JSValue::encode(result);
}

JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, inputIsUTC));
JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, inputTimeType));
thisDateObj->setInternalValue(vm, result);
return JSValue::encode(result);
}

static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC)
static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, WTF::TimeType inputTimeType)
{
JSValue thisValue = exec->thisValue();
if (!thisValue.inherits(DateInstance::info()))
@@ -916,10 +916,10 @@ static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse,

GregorianDateTime gregorianDateTime;
if (numArgsToUse == 3 && std::isnan(milli))
msToGregorianDateTime(vm, 0, true, gregorianDateTime);
msToGregorianDateTime(vm, 0, WTF::UTCTime, gregorianDateTime);
else {
ms = milli - floor(milli / msPerSecond) * msPerSecond;
const GregorianDateTime* other = inputIsUTC
const GregorianDateTime* other = inputTimeType == WTF::UTCTime
? thisDateObj->gregorianDateTimeUTC(exec)
: thisDateObj->gregorianDateTime(exec);
if (!other)
@@ -933,93 +933,93 @@ static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse,
return JSValue::encode(result);
}

JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, inputIsUTC));
JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, inputTimeType));
thisDateObj->setInternalValue(vm, result);
return JSValue::encode(result);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState* exec)
{
const bool inputIsUTC = false;
return setNewValueFromTimeArgs(exec, 1, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::LocalTime;
return setNewValueFromTimeArgs(exec, 1, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState* exec)
{
const bool inputIsUTC = true;
return setNewValueFromTimeArgs(exec, 1, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::UTCTime;
return setNewValueFromTimeArgs(exec, 1, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState* exec)
{
const bool inputIsUTC = false;
return setNewValueFromTimeArgs(exec, 2, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::LocalTime;
return setNewValueFromTimeArgs(exec, 2, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState* exec)
{
const bool inputIsUTC = true;
return setNewValueFromTimeArgs(exec, 2, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::UTCTime;
return setNewValueFromTimeArgs(exec, 2, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState* exec)
{
const bool inputIsUTC = false;
return setNewValueFromTimeArgs(exec, 3, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::LocalTime;
return setNewValueFromTimeArgs(exec, 3, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState* exec)
{
const bool inputIsUTC = true;
return setNewValueFromTimeArgs(exec, 3, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::UTCTime;
return setNewValueFromTimeArgs(exec, 3, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState* exec)
{
const bool inputIsUTC = false;
return setNewValueFromTimeArgs(exec, 4, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::LocalTime;
return setNewValueFromTimeArgs(exec, 4, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState* exec)
{
const bool inputIsUTC = true;
return setNewValueFromTimeArgs(exec, 4, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::UTCTime;
return setNewValueFromTimeArgs(exec, 4, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState* exec)
{
const bool inputIsUTC = false;
return setNewValueFromDateArgs(exec, 1, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::LocalTime;
return setNewValueFromDateArgs(exec, 1, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState* exec)
{
const bool inputIsUTC = true;
return setNewValueFromDateArgs(exec, 1, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::UTCTime;
return setNewValueFromDateArgs(exec, 1, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState* exec)
{
const bool inputIsUTC = false;
return setNewValueFromDateArgs(exec, 2, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::LocalTime;
return setNewValueFromDateArgs(exec, 2, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState* exec)
{
const bool inputIsUTC = true;
return setNewValueFromDateArgs(exec, 2, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::UTCTime;
return setNewValueFromDateArgs(exec, 2, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState* exec)
{
const bool inputIsUTC = false;
return setNewValueFromDateArgs(exec, 3, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::LocalTime;
return setNewValueFromDateArgs(exec, 3, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec)
{
const bool inputIsUTC = true;
return setNewValueFromDateArgs(exec, 3, inputIsUTC);
const WTF::TimeType inputTimeType = WTF::UTCTime;
return setNewValueFromDateArgs(exec, 3, inputTimeType);
}

EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
@@ -1043,7 +1043,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
if (std::isnan(milli))
// Based on ECMA 262 B.2.5 (setYear)
// the time must be reset to +0 if it is NaN.
msToGregorianDateTime(vm, 0, true, gregorianDateTime);
msToGregorianDateTime(vm, 0, WTF::UTCTime, gregorianDateTime);
else {
double secs = floor(milli / msPerSecond);
ms = milli - secs * msPerSecond;
@@ -1059,7 +1059,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
}

gregorianDateTime.setYear(toInt32((year >= 0 && year <= 99) ? (year + 1900) : year));
JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, false));
JSValue result = jsNumber(gregorianDateTimeToMS(vm, gregorianDateTime, ms, WTF::LocalTime));
thisDateObj->setInternalValue(vm, result);
return JSValue::encode(result);
}

0 comments on commit 1fc68a1

Please sign in to comment.