String(new Date(2010,10,1)) is wrong in KRAT, YAKT
https://bugs.webkit.org/show_bug.cgi?id=106750
Reviewed by Darin Adler.
First part of a fix, simplfy date handling code, instead of operating separately
on the UTC-standard and standard-DST offsets, just generate a combined UTC-local
offset (this is what we actually need, and what the OS gives us).
../JavaScriptCore:
* runtime/JSDateMath.cpp:
(JSC::getLocalTimeOffset):
- removed getUTCOffset, converted getDSTOffset -> getLocalTimeOffset
(JSC::gregorianDateTimeToMS):
(JSC::msToGregorianDateTime):
(JSC::parseDateFromNullTerminatedCharacters):
- call getLocalTimeOffset instead of getUTCOffset/getDSTOffset
* runtime/VM.cpp:
(JSC::VM::resetDateCache):
- removed cachedUTCOffset, converted DSTOffsetCache -> LocalTimeOffsetCache
* runtime/VM.h:
(JSC::LocalTimeOffsetCache::LocalTimeOffsetCache):
(JSC::LocalTimeOffsetCache::reset):
(LocalTimeOffsetCache):
- removed cachedUTCOffset, converted DSTOffsetCache -> LocalTimeOffsetCache
../WTF:
* wtf/DateMath.cpp:
(WTF::calculateUTCOffset):
(WTF::calculateDSTOffset):
- made static, now not called from outside of this file.
(WTF::calculateLocalTimeOffset):
- This combines the 2038 related adjustment from calculateDSTOffset with the
maxUnixTime adjustment from calculateDSTOffsetSimple. Then, if HAVE(TM_GMTOFF)
just call getLocalTime, if not use calculateUTCOffset/calculateDSTOffset.
(WTF::parseDateFromNullTerminatedCharacters):
- call calculateLocalTimeOffset instead of calculateUTCOffset/calculateDSTOffset
* wtf/DateMath.h:
(WTF::LocalTimeOffset::LocalTimeOffset):
(LocalTimeOffset):
(WTF::LocalTimeOffset::operator==):
- new struct type, a tuple of UTC-local offset & isDST flag.
- replaced calculateUTCOffset/calculateDSTOffset with calculateLocalTimeOffset
* wtf/GregorianDateTime.cpp:
(WTF::GregorianDateTime::setToCurrentLocalTime):
- call calculateLocalTimeOffset instead of calculateUTCOffset/calculateDSTOffset
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@150833 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp
index 4576352..6e601f1 100644
--- a/Source/JavaScriptCore/runtime/JSDateMath.cpp
+++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp
@@ -127,14 +127,14 @@
return wd;
}
-// Get the DST offset for the time passed in.
+// Get the combined UTC + DST offset for the time passed in.
//
// 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 double getDSTOffset(ExecState* exec, double ms, double utcOffset)
+static LocalTimeOffset localTimeOffset(ExecState* exec, double ms)
{
- DSTOffsetCache& cache = exec->vm().dstOffsetCache;
+ LocalTimeOffsetCache& cache = exec->vm().localTimeOffsetCache;
double start = cache.start;
double end = cache.end;
@@ -146,7 +146,7 @@
double newEnd = end + cache.increment;
if (ms <= newEnd) {
- double endOffset = calculateDSTOffset(newEnd, utcOffset);
+ LocalTimeOffset endOffset = calculateLocalTimeOffset(newEnd);
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
@@ -154,34 +154,33 @@
cache.end = newEnd;
cache.increment = msPerMonth;
return endOffset;
- } else {
- double offset = calculateDSTOffset(ms, utcOffset);
- 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
- // the point in time where the DST offset change occurred. Updated
- // the interval to reflect this and reset the increment.
- cache.start = ms;
- cache.end = newEnd;
- cache.increment = msPerMonth;
- } else {
- // The interval contains a DST offset change and the given time is
- // before it. Adjust the increment to avoid a linear search for
- // the offset change point and change the end of the interval.
- cache.increment /= 3;
- cache.end = ms;
- }
- // Update the offset in the cache and return it.
- cache.offset = offset;
- return offset;
}
+ LocalTimeOffset offset = calculateLocalTimeOffset(ms);
+ 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
+ // the point in time where the DST offset change occurred. Updated
+ // the interval to reflect this and reset the increment.
+ cache.start = ms;
+ cache.end = newEnd;
+ cache.increment = msPerMonth;
+ } else {
+ // The interval contains a DST offset change and the given time is
+ // before it. Adjust the increment to avoid a linear search for
+ // the offset change point and change the end of the interval.
+ cache.increment /= 3;
+ cache.end = ms;
+ }
+ // Update the offset in the cache and return it.
+ cache.offset = offset;
+ return offset;
}
}
// 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.
- double offset = calculateDSTOffset(ms, utcOffset);
+ LocalTimeOffset offset = calculateLocalTimeOffset(ms);
cache.offset = offset;
cache.start = ms;
cache.end = ms;
@@ -189,30 +188,14 @@
return offset;
}
-/*
- * Get the difference in milliseconds between this time zone and UTC (GMT)
- * NOT including DST.
- */
-double getUTCOffset(ExecState* exec)
-{
- double utcOffset = exec->vm().cachedUTCOffset;
- if (!std::isnan(utcOffset))
- return utcOffset;
- exec->vm().cachedUTCOffset = calculateUTCOffset();
- return exec->vm().cachedUTCOffset;
-}
-
double gregorianDateTimeToMS(ExecState* exec, const GregorianDateTime& t, double milliSeconds, bool inputIsUTC)
{
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;
- if (!inputIsUTC) { // convert to UTC
- double utcOffset = getUTCOffset(exec);
- result -= utcOffset;
- result -= getDSTOffset(exec, result, utcOffset);
- }
+ if (!inputIsUTC)
+ result -= localTimeOffset(exec, result).offset;
return result;
}
@@ -220,12 +203,10 @@
// input is UTC
void msToGregorianDateTime(ExecState* exec, double ms, bool outputIsUTC, GregorianDateTime& tm)
{
- double dstOff = 0.0;
- double utcOff = 0.0;
+ LocalTimeOffset localTime(false, 0);
if (!outputIsUTC) {
- utcOff = getUTCOffset(exec);
- dstOff = getDSTOffset(exec, ms, utcOff);
- ms += dstOff + utcOff;
+ localTime = localTimeOffset(exec, ms);
+ ms += localTime.offset;
}
const int year = msToYear(ms);
@@ -237,8 +218,8 @@
tm.setMonthDay(dayInMonthFromDayInYear(tm.yearDay(), isLeapYear(year)));
tm.setMonth(monthFromDayInYear(tm.yearDay(), isLeapYear(year)));
tm.setYear(year);
- tm.setIsDST(dstOff != 0.0);
- tm.setUtcOffset(static_cast<long>((dstOff + utcOff) / WTF::msPerSecond));
+ tm.setIsDST(localTime.isDST);
+ tm.setUtcOffset(localTime.offset / WTF::msPerSecond);
}
double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateString)
@@ -251,11 +232,9 @@
return QNaN;
// fall back to local timezone
- if (!haveTZ) {
- double utcOffset = getUTCOffset(exec);
- double dstOffset = getDSTOffset(exec, ms, utcOffset);
- offset = (utcOffset + dstOffset) / WTF::msPerMinute;
- }
+ if (!haveTZ)
+ offset = localTimeOffset(exec, ms).offset / WTF::msPerMinute;
+
return ms - (offset * WTF::msPerMinute);
}