/* * 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; }
// Returns combined offset in millisecond (UTC + DST). 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 // determining DST. For this reason we shift away from years that localtime can handle but would // return historically accurate information. int year = msToYear(ms); int equivalentYear = equivalentYearForDST(year); if (year != equivalentYear) { bool leapYear = isLeapYear(year); int dayInYearLocal = dayInYear(ms, year); int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear); int month = monthFromDayInYear(dayInYearLocal, leapYear); double day = dateToDaysFrom1970(equivalentYear, month, dayInMonth); ms = (day * msPerDay) + msToMilliseconds(ms); } 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<time_t>(localTimeSeconds); #if HAVE(TM_GMTOFF) tm localTM; getLocalTime(&localTime, &localTM); return LocalTimeOffset(localTM.tm_isdst, localTM.tm_gmtoff * msPerSecond); #else double dstOffset = calculateDSTOffset(localTime, localToUTCTimeOffset); return LocalTimeOffset(dstOffset, localToUTCTimeOffset + dstOffset); #endif }
static int currentFullYear() { double current = currentTimeMS(); double utcOffset = calculateUTCOffset(); double dstOffset = calculateDSTOffset(current, utcOffset); int offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute); current += offset * msPerMinute; DateComponents date; date.setMillisecondsSinceEpochForMonth(current); return date.fullYear(); }
int DateTimeYearFieldElement::defaultValueForStepDown() const { double current = currentTimeMS(); double utcOffset = calculateUTCOffset(); double dstOffset = calculateDSTOffset(current, utcOffset); int offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute); current += offset * msPerMinute; DateComponents date; date.setMillisecondsSinceEpochForMonth(current); return date.fullYear(); }
Decimal MonthInputType::defaultValueForStepUp() const { double current = currentTimeMS(); double utcOffset = calculateUTCOffset(); double dstOffset = calculateDSTOffset(current, utcOffset); int offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute); current += offset * msPerMinute; DateComponents date; date.setMillisecondsSinceEpochForMonth(current); double months = date.monthsSinceEpoch(); ASSERT(std::isfinite(months)); return Decimal::fromDouble(months); }
double parseDateFromNullTerminatedCharacters(const char* dateString) { bool haveTZ; int offset; double ms = parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset); if (isnan(ms)) return NaN; // fall back to local timezone if (!haveTZ) { double utcOffset = calculateUTCOffset(); double dstOffset = calculateDSTOffset(ms, utcOffset); offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute); } return ms - (offset * msPerMinute); }
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) { double utcOffset = calculateUTCOffset(); double dstOffset = calculateDSTOffset(ms, utcOffset); offset = (utcOffset + dstOffset) / msPerMinute; } return ms - (offset * msPerMinute); }
void initializeDates() { #ifndef NDEBUG static bool alreadyInitialized; ASSERT(!alreadyInitialized++); #endif equivalentYearForDST(2000); // Need to call once to initialize a static used in this function. #if PLATFORM(DARWIN) // Register for a notification whenever the time zone changes. uint32_t status = notify_register_check("com.apple.system.timezone", &s_notificationToken); if (status == NOTIFY_STATUS_OK) { s_cachedUTCOffset = calculateUTCOffset(); s_haveCachedUTCOffset = true; } #endif }
/* * Get the difference in milliseconds between this time zone and UTC (GMT) * NOT including DST. */ double getUTCOffset() { #if PLATFORM(DARWIN) if (s_haveCachedUTCOffset) { int notified; uint32_t status = notify_check(s_notificationToken, ¬ified); if (status == NOTIFY_STATUS_OK && !notified) return s_cachedUTCOffset; } #endif int32_t utcOffset = calculateUTCOffset(); #if PLATFORM(DARWIN) // Theoretically, it is possible that several threads will be executing this code at once, in which case we will have a race condition, // and a newer value may be overwritten. In practice, time zones don't change that often. s_cachedUTCOffset = utcOffset; #endif return utcOffset; }
PassRefPtr<SharedBuffer> MHTMLArchive::generateMHTMLData(Page* page, bool useBinaryEncoding) { Vector<PageSerializer::Resource> resources; PageSerializer pageSerializer(&resources); pageSerializer.serialize(page); String boundary = generateRandomBoundary(); String endOfResourceBoundary = makeString("--", boundary, "\r\n"); tm localTM; getCurrentLocalTime(&localTM); String dateString = makeRFC2822DateString(localTM.tm_wday, localTM.tm_mday, localTM.tm_mon, 1900 + localTM.tm_year, localTM.tm_hour, localTM.tm_min, localTM.tm_sec, calculateUTCOffset() / (1000 * 60)); StringBuilder stringBuilder; stringBuilder.append("From: <Saved by WebKit>\r\n"); stringBuilder.append("Subject: "); // We replace non ASCII characters with '?' characters to match IE's behavior. stringBuilder.append(replaceNonPrintableCharacters(page->mainFrame()->document()->title())); stringBuilder.append("\r\nDate: "); stringBuilder.append(dateString); stringBuilder.append("\r\nMIME-Version: 1.0\r\n"); stringBuilder.append("Content-Type: multipart/related;\r\n"); stringBuilder.append("\ttype=\""); stringBuilder.append(page->mainFrame()->document()->suggestedMIMEType()); stringBuilder.append("\";\r\n"); stringBuilder.append("\tboundary=\""); stringBuilder.append(boundary); stringBuilder.append("\"\r\n\r\n"); // We use utf8() below instead of ascii() as ascii() replaces CRLFs with ?? (we still only have put ASCII characters in it). ASSERT(stringBuilder.toString().containsOnlyASCII()); CString asciiString = stringBuilder.toString().utf8(); RefPtr<SharedBuffer> mhtmlData = SharedBuffer::create(); mhtmlData->append(asciiString.data(), asciiString.length()); for (size_t i = 0; i < resources.size(); ++i) { const PageSerializer::Resource& resource = resources[i]; stringBuilder.clear(); stringBuilder.append(endOfResourceBoundary); stringBuilder.append("Content-Type: "); stringBuilder.append(resource.mimeType); const char* contentEncoding = 0; if (useBinaryEncoding) contentEncoding = binary; else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(resource.mimeType) || MIMETypeRegistry::isSupportedNonImageMIMEType(resource.mimeType)) contentEncoding = quotedPrintable; else contentEncoding = base64; stringBuilder.append("\r\nContent-Transfer-Encoding: "); stringBuilder.append(contentEncoding); stringBuilder.append("\r\nContent-Location: "); stringBuilder.append(resource.url); stringBuilder.append("\r\n\r\n"); asciiString = stringBuilder.toString().utf8(); mhtmlData->append(asciiString.data(), asciiString.length()); if (!strcmp(contentEncoding, binary)) { const char* data; size_t position = 0; while (size_t length = resource.data->getSomeData(data, position)) { mhtmlData->append(data, length); position += length; } } else { // FIXME: ideally we would encode the content as a stream without having to fetch it all. const char* data = resource.data->data(); size_t dataLength = resource.data->size(); Vector<char> encodedData; if (!strcmp(contentEncoding, quotedPrintable)) { quotedPrintableEncode(data, dataLength, encodedData); mhtmlData->append(encodedData.data(), encodedData.size()); mhtmlData->append("\r\n", 2); } else { ASSERT(!strcmp(contentEncoding, base64)); // We are not specifying insertLFs = true below as it would cut the lines with LFs and MHTML requires CRLFs. base64Encode(data, dataLength, encodedData); const size_t maximumLineLength = 76; size_t index = 0; size_t encodedDataLength = encodedData.size(); do { size_t lineLength = std::min(encodedDataLength - index, maximumLineLength); mhtmlData->append(encodedData.data() + index, lineLength); mhtmlData->append("\r\n", 2); index += maximumLineLength; } while (index < encodedDataLength); } } } asciiString = makeString("--", boundary, "--\r\n").utf8(); mhtmlData->append(asciiString.data(), asciiString.length()); return mhtmlData.release(); }