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:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@175078 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp
index c8a2acc..1482e31 100644
--- a/Source/JavaScriptCore/runtime/JSDateMath.cpp
+++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp
@@ -132,13 +132,14 @@
 // NOTE: The implementation relies on the fact that no time zones have
 // more than one daylight savings offset change per month.
 // If this function is called with NaN it returns NaN.
-static LocalTimeOffset localTimeOffset(VM& vm, double ms)
+static LocalTimeOffset localTimeOffset(VM& vm, double ms, WTF::TimeType inputTimeType = WTF::UTCTime)
 {
     LocalTimeOffsetCache& cache = vm.localTimeOffsetCache;
     double start = cache.start;
     double end = cache.end;
+    WTF::TimeType cachedTimeType = cache.timeType;
 
-    if (start <= ms) {
+    if (cachedTimeType == inputTimeType && start <= ms) {
         // If the time fits in the cached interval, return the cached offset.
         if (ms <= end) return cache.offset;
 
@@ -146,7 +147,7 @@
         double newEnd = end + cache.increment;
 
         if (ms <= newEnd) {
-            LocalTimeOffset endOffset = calculateLocalTimeOffset(newEnd);
+            LocalTimeOffset endOffset = calculateLocalTimeOffset(newEnd, inputTimeType);
             if (cache.offset == endOffset) {
                 // If the offset at the end of the new interval still matches
                 // the offset in the cache, we grow the cached time interval
@@ -155,7 +156,7 @@
                 cache.increment = msPerMonth;
                 return endOffset;
             }
-            LocalTimeOffset offset = calculateLocalTimeOffset(ms);
+            LocalTimeOffset offset = calculateLocalTimeOffset(ms, inputTimeType);
             if (offset == endOffset) {
                 // The offset at the given time is equal to the offset at the
                 // new end of the interval, so that means that we've just skipped
@@ -180,31 +181,31 @@
     // Compute the DST offset for the time and shrink the cache interval
     // to only contain the time. This allows fast repeated DST offset
     // computations for the same time.
-    LocalTimeOffset offset = calculateLocalTimeOffset(ms);
+    LocalTimeOffset offset = calculateLocalTimeOffset(ms, inputTimeType);
     cache.offset = offset;
     cache.start = ms;
     cache.end = ms;
     cache.increment = msPerMonth;
+    cache.timeType = inputTimeType;
     return offset;
 }
 
-double gregorianDateTimeToMS(VM& vm, const GregorianDateTime& t, double milliSeconds, bool inputIsUTC)
+double gregorianDateTimeToMS(VM& vm, const GregorianDateTime& t, double milliSeconds, WTF::TimeType inputTimeType)
 {
     double day = dateToDaysFrom1970(t.year(), t.month(), t.monthDay());
     double ms = timeToMS(t.hour(), t.minute(), t.second(), milliSeconds);
-    double result = (day * WTF::msPerDay) + ms;
+    double localTimeResult = (day * WTF::msPerDay) + ms;
+    double localToUTCTimeOffset = inputTimeType == LocalTime
+        ? localTimeOffset(vm, localTimeResult, inputTimeType).offset : 0;
 
-    if (!inputIsUTC)
-        result -= localTimeOffset(vm, result).offset;
-
-    return result;
+    return localTimeResult - localToUTCTimeOffset;
 }
 
 // input is UTC
-void msToGregorianDateTime(VM& vm, double ms, bool outputIsUTC, GregorianDateTime& tm)
+void msToGregorianDateTime(VM& vm, double ms, WTF::TimeType outputTimeType, GregorianDateTime& tm)
 {
     LocalTimeOffset localTime;
-    if (!outputIsUTC) {
+    if (outputTimeType == WTF::LocalTime) {
         localTime = localTimeOffset(vm, ms);
         ms += localTime.offset;
     }
@@ -226,15 +227,15 @@
 {
     bool haveTZ;
     int offset;
-    double ms = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset);
-    if (std::isnan(ms))
+    double localTimeMS = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset);
+    if (std::isnan(localTimeMS))
         return std::numeric_limits<double>::quiet_NaN();
 
-    // fall back to local timezone
+    // fall back to local timezone.
     if (!haveTZ)
-        offset = localTimeOffset(vm, ms).offset / WTF::msPerMinute;
+        offset = localTimeOffset(vm, localTimeMS, WTF::LocalTime).offset / WTF::msPerMinute;
 
-    return ms - (offset * WTF::msPerMinute);
+    return localTimeMS - (offset * WTF::msPerMinute);
 }
 
 double parseDate(VM& vm, const String& date)