diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
commit | e15dd966d523731101f70ccf768bba12435a0208 (patch) | |
tree | ae9cb828a24ded2585a41af3f21411523b47897d /Source/JavaScriptCore/runtime/JSDateMath.cpp | |
download | WebKitGtk-tarball-e15dd966d523731101f70ccf768bba12435a0208.tar.gz |
webkitgtk-2.10.2webkitgtk-2.10.2
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSDateMath.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSDateMath.cpp | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp new file mode 100644 index 000000000..1482e312f --- /dev/null +++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2006, 2007, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * Copyright (C) 2010 &yet, LLC. (nate@andyet.net) + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Alternatively, the contents of this file may be used under the terms + * of either the Mozilla Public License Version 1.1, found at + * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public + * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html + * (the "GPL"), in which case the provisions of the MPL or the GPL are + * applicable instead of those above. If you wish to allow use of your + * version of this file only under the terms of one of those two + * licenses (the MPL or the GPL) and not to allow others to use your + * version of this file under the LGPL, indicate your decision by + * deletingthe provisions above and replace them with the notice and + * other provisions required by the MPL or the GPL, as the case may be. + * If you do not delete the provisions above, a recipient may use your + * version of this file under any of the LGPL, the MPL or the GPL. + + * Copyright 2006-2008 the V8 project authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSDateMath.h" + +#include "JSObject.h" +#include "JSScope.h" +#include "JSCInlines.h" + +#include <algorithm> +#include <limits.h> +#include <limits> +#include <stdint.h> +#include <time.h> +#include <wtf/ASCIICType.h> +#include <wtf/Assertions.h> +#include <wtf/CurrentTime.h> +#include <wtf/MathExtras.h> +#include <wtf/StdLibExtras.h> +#include <wtf/StringExtras.h> +#include <wtf/text/StringBuilder.h> + +#if HAVE(ERRNO_H) +#include <errno.h> +#endif + +#if HAVE(SYS_TIME_H) +#include <sys/time.h> +#endif + +#if HAVE(SYS_TIMEB_H) +#include <sys/timeb.h> +#endif + +using namespace WTF; + +namespace JSC { + +static inline double timeToMS(double hour, double min, double sec, double ms) +{ + return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms); +} + +static inline int msToSeconds(double ms) +{ + double result = fmod(floor(ms / msPerSecond), secondsPerMinute); + if (result < 0) + result += secondsPerMinute; + return static_cast<int>(result); +} + +// 0: Sunday, 1: Monday, etc. +static inline int msToWeekDay(double ms) +{ + int wd = (static_cast<int>(msToDays(ms)) + 4) % 7; + if (wd < 0) + wd += 7; + return wd; +} + +// 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 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 (cachedTimeType == inputTimeType && start <= ms) { + // If the time fits in the cached interval, return the cached offset. + if (ms <= end) return cache.offset; + + // Compute a possible new interval end. + double newEnd = end + cache.increment; + + if (ms <= 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 + // and return the offset. + cache.end = newEnd; + cache.increment = msPerMonth; + return endOffset; + } + 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 + // 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. + 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, WTF::TimeType inputTimeType) +{ + double day = dateToDaysFrom1970(t.year(), t.month(), t.monthDay()); + double ms = timeToMS(t.hour(), t.minute(), t.second(), milliSeconds); + double localTimeResult = (day * WTF::msPerDay) + ms; + double localToUTCTimeOffset = inputTimeType == LocalTime + ? localTimeOffset(vm, localTimeResult, inputTimeType).offset : 0; + + return localTimeResult - localToUTCTimeOffset; +} + +// input is UTC +void msToGregorianDateTime(VM& vm, double ms, WTF::TimeType outputTimeType, GregorianDateTime& tm) +{ + LocalTimeOffset localTime; + if (outputTimeType == WTF::LocalTime) { + localTime = localTimeOffset(vm, ms); + ms += localTime.offset; + } + + const int year = msToYear(ms); + tm.setSecond(msToSeconds(ms)); + tm.setMinute(msToMinutes(ms)); + tm.setHour(msToHours(ms)); + tm.setWeekDay(msToWeekDay(ms)); + tm.setYearDay(dayInYear(ms, year)); + tm.setMonthDay(dayInMonthFromDayInYear(tm.yearDay(), isLeapYear(year))); + tm.setMonth(monthFromDayInYear(tm.yearDay(), isLeapYear(year))); + tm.setYear(year); + tm.setIsDST(localTime.isDST); + tm.setUtcOffset(localTime.offset / WTF::msPerSecond); +} + +double parseDateFromNullTerminatedCharacters(VM& vm, const char* dateString) +{ + bool haveTZ; + int offset; + double localTimeMS = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset); + if (std::isnan(localTimeMS)) + return std::numeric_limits<double>::quiet_NaN(); + + // fall back to local timezone. + if (!haveTZ) + offset = localTimeOffset(vm, localTimeMS, WTF::LocalTime).offset / WTF::msPerMinute; + + return localTimeMS - (offset * WTF::msPerMinute); +} + +double parseDate(VM& vm, const String& date) +{ + if (date == vm.cachedDateString) + return vm.cachedDateStringValue; + double value = parseES5DateFromNullTerminatedCharacters(date.utf8().data()); + if (std::isnan(value)) + value = parseDateFromNullTerminatedCharacters(vm, date.utf8().data()); + vm.cachedDateString = date; + vm.cachedDateStringValue = value; + return value; +} + +} // namespace JSC |