String(new Date(Mar 30 2014 01:00:00)) is wrong in CET
authorCarlos Garcia Campos <carlosgc@webkit.org>
Fri, 6 Mar 2015 07:33:11 +0000 (07:33 +0000)
committerAlberto Garcia <berto@igalia.com>
Fri, 6 Mar 2015 07:33:11 +0000 (07:33 +0000)
===================================================================

Gbp-Pq: Name fix-date.patch

Source/JavaScriptCore/runtime/DateConstructor.cpp
Source/JavaScriptCore/runtime/DateInstance.cpp
Source/JavaScriptCore/runtime/DatePrototype.cpp
Source/JavaScriptCore/runtime/JSDateMath.cpp
Source/JavaScriptCore/runtime/JSDateMath.h
Source/JavaScriptCore/runtime/VM.h
Source/WTF/wtf/DateMath.cpp
Source/WTF/wtf/DateMath.h

index 49a1c369554131e09d5b840a37a9223960af9fb1..a310d47181cd4a970a94ee7113e2d50365ee09af 100644 (file)
@@ -166,7 +166,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);
         }
     }
 
@@ -190,7 +190,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)));
 }
 
@@ -244,7 +244,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
index c1749f6fbd7027da75cbd07687ad5ab0450e1ec9..e095f882c8ae337ef86c65f1ea792c92e0ac9f72 100644 (file)
@@ -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;
index 5eaf86af654ac03857d515851a1bfd329cdfad6d..b9d8262f636de24a27518bb513546f358d37f1b1 100644 (file)
@@ -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);
 }
index c8a2acc7e89331afd8e5025cb383b3ddc4acb7b7..1482e312f377082e37c71554f8fcd7a2debfe1e6 100644 (file)
@@ -132,13 +132,14 @@ static inline int msToWeekDay(double ms)
 // 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 @@ static LocalTimeOffset localTimeOffset(VM& vm, double ms)
         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 @@ static LocalTimeOffset localTimeOffset(VM& vm, double ms)
                 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 @@ static LocalTimeOffset localTimeOffset(VM& vm, double ms)
     // 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 @@ double parseDateFromNullTerminatedCharacters(VM& vm, const char* dateString)
 {
     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)
index 9a1ae30835eabba6bc3ab3b697e5bdb6721cbe42..4e4d16ff566095571a33c1bd21524ebbc68b859f 100644 (file)
@@ -50,8 +50,8 @@ namespace JSC {
 
 class VM;
 
-JS_EXPORT_PRIVATE void msToGregorianDateTime(VM&, double, bool outputIsUTC, GregorianDateTime&);
-JS_EXPORT_PRIVATE double gregorianDateTimeToMS(VM&, const GregorianDateTime&, double, bool inputIsUTC);
+JS_EXPORT_PRIVATE void msToGregorianDateTime(VM&, double, WTF::TimeType outputTimeType, GregorianDateTime&);
+JS_EXPORT_PRIVATE double gregorianDateTimeToMS(VM&, const GregorianDateTime&, double, WTF::TimeType inputTimeType);
 JS_EXPORT_PRIVATE double getUTCOffset(VM&);
 JS_EXPORT_PRIVATE double parseDateFromNullTerminatedCharacters(VM&, const char* dateString);
 JS_EXPORT_PRIVATE double parseDate(VM&, const WTF::String&);
index 37ac9b16f3764def3b686e43810348722037cf41..c088b4269eaffc2a7a622247789a59bd5b2d2758 100644 (file)
@@ -133,6 +133,7 @@ struct LocalTimeOffsetCache {
         : start(0.0)
         , end(-1.0)
         , increment(0.0)
+        , timeType(WTF::UTCTime)
     {
     }
 
@@ -142,12 +143,14 @@ struct LocalTimeOffsetCache {
         start = 0.0;
         end = -1.0;
         increment = 0.0;
+        timeType = WTF::UTCTime;
     }
 
     LocalTimeOffset offset;
     double start;
     double end;
     double increment;
+    WTF::TimeType timeType;
 };
 
 class ConservativeRoots;
index 6ee36d3c5fac57791b77b11d8178bc5243df8b5b..29824a31a37b421ac3e7ca1a3d72fe48816d470e 100644 (file)
@@ -363,8 +363,6 @@ int equivalentYearForDST(int year)
     return year;
 }
 
-#if !HAVE(TM_GMTOFF)
-
 static int32_t calculateUTCOffset()
 {
 #if OS(WINDOWS)
@@ -406,6 +404,8 @@ static int32_t calculateUTCOffset()
 #endif
 }
 
+#if !HAVE(TM_GMTOFF)
+
 #if OS(WINDOWS)
 // Code taken from http://support.microsoft.com/kb/167296
 static void UnixTimeToFileTime(time_t t, LPFILETIME pft)
@@ -467,8 +467,16 @@ static double calculateDSTOffset(time_t localTime, double utcOffset)
 #endif
 
 // Returns combined offset in millisecond (UTC + DST).
-LocalTimeOffset calculateLocalTimeOffset(double ms)
+LocalTimeOffset calculateLocalTimeOffset(double ms, TimeType inputTimeType)
 {
+#if HAVE(TM_GMTOFF)
+    double localToUTCTimeOffset = inputTimeType == LocalTime ? calculateUTCOffset() : 0;
+#else
+    double localToUTCTimeOffset = calculateUTCOffset();
+#endif
+    if (inputTimeType == LocalTime)
+        ms -= localToUTCTimeOffset;
+
     // On Mac OS X, the call to localtime (see calculateDSTOffset) will return historically accurate
     // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript
     // standard explicitly dictates that historical information should not be considered when
@@ -498,9 +506,8 @@ LocalTimeOffset calculateLocalTimeOffset(double ms)
     getLocalTime(&localTime, &localTM);
     return LocalTimeOffset(localTM.tm_isdst, localTM.tm_gmtoff * msPerSecond);
 #else
-    double utcOffset = calculateUTCOffset();
-    double dstOffset = calculateDSTOffset(localTime, utcOffset);
-    return LocalTimeOffset(dstOffset, utcOffset + dstOffset);
+    double dstOffset = calculateDSTOffset(localTime, localToUTCTimeOffset);
+    return LocalTimeOffset(dstOffset, localToUTCTimeOffset + dstOffset);
 #endif
 }
 
@@ -1091,7 +1098,7 @@ double parseDateFromNullTerminatedCharacters(const char* dateString)
 
     // fall back to local timezone
     if (!haveTZ)
-        offset = calculateLocalTimeOffset(ms).offset / msPerMinute;
+        offset = calculateLocalTimeOffset(ms, LocalTime).offset / msPerMinute; // ms value is in local time milliseconds.
 
     return ms - (offset * msPerMinute);
 }
index c8ae0d912f684dc267acadf67285ac1433515130..73889a56821095107cb76142a3c88bf14dd3f65e 100644 (file)
 
 namespace WTF {
 
+enum TimeType {
+    UTCTime = 0,
+    LocalTime
+};
+
 struct LocalTimeOffset {
     LocalTimeOffset()
         : isDST(false)
@@ -126,7 +131,7 @@ WTF_EXPORT_PRIVATE int monthFromDayInYear(int dayInYear, bool leapYear);
 WTF_EXPORT_PRIVATE int dayInMonthFromDayInYear(int dayInYear, bool leapYear);
 
 // Returns combined offset in millisecond (UTC + DST).
-WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds);
+WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double utcInMilliseconds, TimeType = UTCTime);
 
 } // namespace WTF