From: Hojong Han Date: Mon, 12 Aug 2013 23:49:18 +0000 (+0900) Subject: Simplify date handling code X-Git-Tag: 2.2.1_release~313 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bc646547a3d43c5086ffb42c80dad6895e69d2e1;p=framework%2Fweb%2Fwebkit-efl.git Simplify date handling code [Title] Simplify date handling code [Issue#] VPSS-1105 [Problem] new Date(2010,10,1) with timezone set to +4 (MSK) returns "Sun Oct 31 2010 01:00:00 GMT+0400 (MSK)" [Cause] Operating seperately on the UTC-standard and standard-DST offsets [Solution] Generate a combined UTC-local offset This patch is based on commit-id ad805ed257b0997c5333bb8967e23cc1c24f4208 on Webkit-trunk Change-Id: Ie96e028c5d8a9cbee01449074a03a8f82562f468 --- diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp index fcf1c43..1f586e8 100644 --- a/Source/JavaScriptCore/runtime/JSDateMath.cpp +++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp @@ -126,14 +126,14 @@ static inline int msToWeekDay(double ms) 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 getLocalTimeOffset(ExecState* exec, double ms) { - DSTOffsetCache& cache = exec->globalData().dstOffsetCache; + LocalTimeOffsetCache& cache = exec->globalData().localTimeOffsetCache; double start = cache.start; double end = cache.end; @@ -145,7 +145,7 @@ static double getDSTOffset(ExecState* exec, double ms, double utcOffset) 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 @@ -153,34 +153,33 @@ static double getDSTOffset(ExecState* exec, double ms, double utcOffset) cache.end = newEnd; cache.increment = msPerMonth; return endOffset; + } + 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 { - 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; + // 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; @@ -188,30 +187,15 @@ static double getDSTOffset(ExecState* exec, double ms, double utcOffset) return offset; } -/* - * Get the difference in milliseconds between this time zone and UTC (GMT) - * NOT including DST. - */ -double getUTCOffset(ExecState* exec) -{ - double utcOffset = exec->globalData().cachedUTCOffset; - if (!isnan(utcOffset)) - return utcOffset; - exec->globalData().cachedUTCOffset = calculateUTCOffset(); - return exec->globalData().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); - } + // convert to UTC + if (!inputIsUTC) + result -= getLocalTimeOffset(exec, result).offset; return result; } @@ -219,12 +203,10 @@ double gregorianDateTimeToMS(ExecState* exec, const GregorianDateTime& t, double // input is UTC void msToGregorianDateTime(ExecState* exec, double ms, bool outputIsUTC, GregorianDateTime& tm) { - double dstOff = 0.0; - double utcOff = 0.0; + LocalTimeOffset localTimeOffset(false, 0); if (!outputIsUTC) { - utcOff = getUTCOffset(exec); - dstOff = getDSTOffset(exec, ms, utcOff); - ms += dstOff + utcOff; + localTimeOffset = getLocalTimeOffset(exec, ms); + ms += localTimeOffset.offset; } const int year = msToYear(ms); @@ -236,8 +218,8 @@ void msToGregorianDateTime(ExecState* exec, double ms, bool outputIsUTC, Gregori 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((dstOff + utcOff) / WTF::msPerSecond)); + tm.setIsDST(localTimeOffset.isDST); + tm.setUtcOffset(localTimeOffset.offset / WTF::msPerSecond); } double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateString) @@ -250,11 +232,8 @@ double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateSt return std::numeric_limits::quiet_NaN(); // fall back to local timezone - if (!haveTZ) { - double utcOffset = getUTCOffset(exec); - double dstOffset = getDSTOffset(exec, ms, utcOffset); - offset = static_cast((utcOffset + dstOffset) / WTF::msPerMinute); - } + if (!haveTZ) + offset = getLocalTimeOffset(exec, ms).offset / WTF::msPerMinute; return ms - (offset * WTF::msPerMinute); } diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index c78cf5a..b093716 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -157,7 +157,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , sizeOfLastScratchBuffer(0) #endif , dynamicGlobalObject(0) - , cachedUTCOffset(std::numeric_limits::quiet_NaN()) , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth) , m_enabledProfiler(0) , m_regExpCache(new RegExpCache(this)) @@ -385,8 +384,7 @@ JSGlobalData::ClientData::~ClientData() void JSGlobalData::resetDateCache() { - cachedUTCOffset = std::numeric_limits::quiet_NaN(); - dstOffsetCache.reset(); + localTimeOffsetCache.reset(); cachedDateString = UString(); cachedDateStringValue = std::numeric_limits::quiet_NaN(); dateInstanceCache.reset(); diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index d185e18..c3be3d5 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -46,6 +46,7 @@ #include "TimeoutChecker.h" #include "WeakRandom.h" #include +#include #include #include #include @@ -84,21 +85,22 @@ namespace JSC { struct HashTable; struct Instruction; - struct DSTOffsetCache { - DSTOffsetCache() + struct LocalTimeOffsetCache { + LocalTimeOffsetCache() + : offset(false, 0) { reset(); } void reset() { - offset = 0.0; + offset = LocalTimeOffset(false, 0); start = 0.0; end = -1.0; increment = 0.0; } - double offset; + LocalTimeOffset offset; double start; double end; double increment; @@ -357,8 +359,7 @@ namespace JSC { HashSet stringRecursionCheckVisitedObjects; - double cachedUTCOffset; - DSTOffsetCache dstOffsetCache; + LocalTimeOffsetCache localTimeOffsetCache; UString cachedDateString; double cachedDateStringValue; diff --git a/Source/WTF/wtf/DateMath.cpp b/Source/WTF/wtf/DateMath.cpp index e3fc329..b964261 100644 --- a/Source/WTF/wtf/DateMath.cpp +++ b/Source/WTF/wtf/DateMath.cpp @@ -356,7 +356,9 @@ int equivalentYearForDST(int year) return year; } -int32_t calculateUTCOffset() +#if !HAVE(TM_GMTOFF) + +static int32_t calculateUTCOffset() { #if OS(WINDOWS) TIME_ZONE_INFORMATION timeZoneInformation; @@ -400,23 +402,15 @@ int32_t calculateUTCOffset() /* * Get the DST offset for the time passed in. */ -static double calculateDSTOffsetSimple(double localTimeSeconds, double utcOffset) +static double calculateDSTOffset(time_t localTime, double utcOffset) { - if (localTimeSeconds > maxUnixTime) - localTimeSeconds = maxUnixTime; - else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0) - localTimeSeconds += secondsPerDay; - //input is UTC so we have to shift back to local time to determine DST thus the + getUTCOffset() - double offsetTime = (localTimeSeconds * msPerSecond) + utcOffset; + double offsetTime = (localTime * msPerSecond) + utcOffset; // Offset from UTC but doesn't include DST obviously int offsetHour = msToHours(offsetTime); int offsetMinute = msToMinutes(offsetTime); - // FIXME: time_t has a potential problem in 2038 - time_t localTime = static_cast(localTimeSeconds); - tm localTM; getLocalTime(&localTime, &localTM); @@ -428,10 +422,12 @@ static double calculateDSTOffsetSimple(double localTimeSeconds, double utcOffset return (diff * msPerSecond); } -// Get the DST offset, given a time in UTC -double calculateDSTOffset(double ms, double utcOffset) +#endif + +// Returns combined offset in millisecond (UTC + DST). +LocalTimeOffset calculateLocalTimeOffset(double ms) { - // On Mac OS X, the call to localtime (see calculateDSTOffsetSimple) will return historically accurate + // 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 // determining DST. For this reason we shift away from years that localtime can handle but would @@ -447,7 +443,23 @@ double calculateDSTOffset(double ms, double utcOffset) ms = (day * msPerDay) + msToMilliseconds(ms); } - return calculateDSTOffsetSimple(ms / msPerSecond, utcOffset); + double localTimeSeconds = ms / msPerSecond; + if (localTimeSeconds > maxUnixTime) + localTimeSeconds = maxUnixTime; + else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0) + localTimeSeconds += secondsPerDay; + // FIXME: time_t has a potential problem in 2038 + time_t localTime = static_cast(localTimeSeconds); + +#if HAVE(TM_GMTOFF) + tm localTM; + 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); +#endif } void initializeDates() @@ -1026,11 +1038,8 @@ double parseDateFromNullTerminatedCharacters(const char* dateString) return std::numeric_limits::quiet_NaN(); // fall back to local timezone - if (!haveTZ) { - double utcOffset = calculateUTCOffset(); - double dstOffset = calculateDSTOffset(ms, utcOffset); - offset = static_cast((utcOffset + dstOffset) / msPerMinute); - } + if (!haveTZ) + offset = calculateLocalTimeOffset(ms).offset / msPerMinute; return ms - (offset * msPerMinute); } diff --git a/Source/WTF/wtf/DateMath.h b/Source/WTF/wtf/DateMath.h index 508fdc3..1ccb333 100644 --- a/Source/WTF/wtf/DateMath.h +++ b/Source/WTF/wtf/DateMath.h @@ -101,8 +101,23 @@ WTF_EXPORT_PRIVATE int monthFromDayInYear(int dayInYear, bool leapYear); WTF_EXPORT_PRIVATE int dayInMonthFromDayInYear(int dayInYear, bool leapYear); // Returns offset milliseconds for UTC and DST. -WTF_EXPORT_PRIVATE int32_t calculateUTCOffset(); -WTF_EXPORT_PRIVATE double calculateDSTOffset(double ms, double utcOffset); +struct LocalTimeOffset { + LocalTimeOffset(bool isDST, int offset) + : isDST(isDST) + , offset(offset) + { + } + + bool operator==(const LocalTimeOffset& other) + { + return isDST == other.isDST && offset == other.offset; + } + + bool isDST; + int offset; +}; +// Returns combined offset in millisecond (UTC + DST). +WTF_EXPORT_PRIVATE LocalTimeOffset calculateLocalTimeOffset(double); } // namespace WTF @@ -122,7 +137,7 @@ using WTF::msToHours; using WTF::secondsPerMinute; using WTF::parseDateFromNullTerminatedCharacters; using WTF::makeRFC2822DateString; -using WTF::calculateUTCOffset; -using WTF::calculateDSTOffset; +using WTF::LocalTimeOffset; +using WTF::calculateLocalTimeOffset; #endif // DateMath_h diff --git a/Source/WTF/wtf/GregorianDateTime.cpp b/Source/WTF/wtf/GregorianDateTime.cpp index 61f73bf..5560984 100644 --- a/Source/WTF/wtf/GregorianDateTime.cpp +++ b/Source/WTF/wtf/GregorianDateTime.cpp @@ -78,9 +78,7 @@ void GregorianDateTime::setToCurrentLocalTime() #if HAVE(TM_GMTOFF) m_utcOffset = localTM.tm_gmtoff; #else - int utcOffset = calculateUTCOffset(); - utcOffset += calculateDSTOffset(localTime * msPerSecond, utcOffset); - m_utcOffset = utcOffset / msPerSecond; + m_utcOffset = calculateLocalTimeOffset(localTime * msPerSecond).offset / msPerSecond; #endif #endif } diff --git a/Source/WTF/wtf/Platform.h b/Source/WTF/wtf/Platform.h index 5e46153..e87123a 100755 --- a/Source/WTF/wtf/Platform.h +++ b/Source/WTF/wtf/Platform.h @@ -781,6 +781,7 @@ com) : Patch to do not adjust cover rect as fixed pixel size*/ #define ENABLE_TIZEN_JSC_CACHEFLUSH_PAGE_BY_PAGE 1 /* Hojong Han(hojong.han@samsung.com) : Fix YarrJIT crash */ #define ENABLE_TIZEN_SET_PROPERTY_ATTRIBUTE_CORRECTLY 1 /* Hojong Han(hojong.han@samsung.com) : Fix overwritting Read-only property, set from WRT */ #define ENABLE_TIZEN_JSC_SKIP_PROPERTY_TABLE_ERROR 1 /* Hojong Han(hojong.han@samsung.com) : Skip property table error */ +#define ENABLE_TIZEN_GENERATE_COMBINED_UTC_LOCAL 1 /* Hojong Han(hojong.han@samsung.com) : Simplify date handling code */ #define ENABLE_TIZEN_WRT_LAUNCHING_PERFORMANCE 1 /* Byungwoo Lee(bw80.lee@samsung.com) : Local patches to enhance web app launching performance */ diff --git a/Source/WebCore/html/BaseDateAndTimeInputType.cpp b/Source/WebCore/html/BaseDateAndTimeInputType.cpp index 921fcdb..d0d4f26 100644 --- a/Source/WebCore/html/BaseDateAndTimeInputType.cpp +++ b/Source/WebCore/html/BaseDateAndTimeInputType.cpp @@ -84,9 +84,13 @@ bool BaseDateAndTimeInputType::typeMismatch() const Decimal BaseDateAndTimeInputType::defaultValueForStepUp() const { double ms = currentTimeMS(); +#if ENABLE(TIZEN_GENERATE_COMBINED_UTC_LOCAL) + int offset = calculateLocalTimeOffset(ms).offset / msPerMinute; +#else double utcOffset = calculateUTCOffset(); double dstOffset = calculateDSTOffset(ms, utcOffset); int offset = static_cast((utcOffset + dstOffset) / msPerMinute); +#endif return Decimal::fromDouble(ms + (offset * msPerMinute)); } diff --git a/Source/WebCore/html/MonthInputType.cpp b/Source/WebCore/html/MonthInputType.cpp index 70afa69..9deb4bc 100644 --- a/Source/WebCore/html/MonthInputType.cpp +++ b/Source/WebCore/html/MonthInputType.cpp @@ -85,9 +85,13 @@ String MonthInputType::serializeWithMilliseconds(double value) const Decimal MonthInputType::defaultValueForStepUp() const { double current = currentTimeMS(); +#if ENABLE(TIZEN_GENERATE_COMBINED_UTC_LOCAL) + int offset = calculateLocalTimeOffset(current).offset / msPerMinute; +#else double utcOffset = calculateUTCOffset(); double dstOffset = calculateDSTOffset(current, utcOffset); int offset = static_cast((utcOffset + dstOffset) / msPerMinute); +#endif current += offset * msPerMinute; DateComponents date; diff --git a/Source/WebCore/html/TimeInputType.cpp b/Source/WebCore/html/TimeInputType.cpp index 052b887..7197412 100644 --- a/Source/WebCore/html/TimeInputType.cpp +++ b/Source/WebCore/html/TimeInputType.cpp @@ -67,9 +67,13 @@ DateComponents::Type TimeInputType::dateType() const Decimal TimeInputType::defaultValueForStepUp() const { double current = currentTimeMS(); +#if ENABLE(TIZEN_GENERATE_COMBINED_UTC_LOCAL) + int offset = calculateLocalTimeOffset(current).offset / msPerMinute; +#else double utcOffset = calculateUTCOffset(); double dstOffset = calculateDSTOffset(current, utcOffset); int offset = static_cast((utcOffset + dstOffset) / msPerMinute); +#endif current += offset * msPerMinute; DateComponents date;