// 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; }
Decimal TimeInputType::defaultValueForStepUp() const { double current = currentTimeMS(); int offset = calculateLocalTimeOffset(current).offset / msPerMinute; current += offset * msPerMinute; DateComponents date; date.setMillisecondsSinceMidnight(current); double milliseconds = date.millisecondsSinceEpoch(); ASSERT(std::isfinite(milliseconds)); return Decimal::fromDouble(milliseconds); }
void GregorianDateTime::setToCurrentLocalTime() { #if OS(WINDOWS) SYSTEMTIME systemTime; GetLocalTime(&systemTime); TIME_ZONE_INFORMATION timeZoneInformation; DWORD timeZoneId = GetTimeZoneInformation(&timeZoneInformation); LONG bias = 0; if (timeZoneId != TIME_ZONE_ID_INVALID) { bias = timeZoneInformation.Bias; if (timeZoneId == TIME_ZONE_ID_DAYLIGHT) bias += timeZoneInformation.DaylightBias; else if ((timeZoneId == TIME_ZONE_ID_STANDARD) || (timeZoneId == TIME_ZONE_ID_UNKNOWN)) bias += timeZoneInformation.StandardBias; else ASSERT(0); } m_year = systemTime.wYear; m_month = systemTime.wMonth - 1; m_monthDay = systemTime.wDay; m_yearDay = dayInYear(m_year, m_month, m_monthDay); m_weekDay = systemTime.wDayOfWeek; m_hour = systemTime.wHour; m_minute = systemTime.wMinute; m_second = systemTime.wSecond; m_utcOffset = -bias * secondsPerMinute; m_isDST = timeZoneId == TIME_ZONE_ID_DAYLIGHT ? 1 : 0; #else tm localTM; time_t localTime = time(0); localtime_r(&localTime, &localTM); m_year = localTM.tm_year + 1900; m_month = localTM.tm_mon; m_monthDay = localTM.tm_mday; m_yearDay = localTM.tm_yday; m_weekDay = localTM.tm_wday; m_hour = localTM.tm_hour; m_minute = localTM.tm_min; m_second = localTM.tm_sec; m_isDST = localTM.tm_isdst; #if HAVE(TM_GMTOFF) m_utcOffset = localTM.tm_gmtoff; #else m_utcOffset = calculateLocalTimeOffset(localTime * msPerSecond).offset / msPerSecond; #endif #endif }
double parseDateFromNullTerminatedCharacters(const char* dateString) { bool haveTZ; int offset; double ms = parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset); if (std::isnan(ms)) return std::numeric_limits<double>::quiet_NaN(); // fall back to local timezone if (!haveTZ) offset = calculateLocalTimeOffset(ms).offset / msPerMinute; return ms - (offset * msPerMinute); }
double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateString) { Q_ASSERT(exec); bool haveTZ; int offset; double ms = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset); if (std::isnan(ms)) return NaN; // fall back to local timezone if (!haveTZ) offset = calculateLocalTimeOffset(ms).offset / msPerMinute; return ms - (offset * WTF::msPerMinute); }