void initializeDates() { #ifndef NDEBUG static bool alreadyInitialized; ASSERT(!alreadyInitialized++); #endif equivalentYearForDST(2000); // Need to call once to initialize a static used in this function. }
static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, LocaleDateTimeFormat format) { #if HAVE(LANGINFO_H) static const nl_item formats[] = { D_T_FMT, D_FMT, T_FMT }; #elif PLATFORM(WINCE) && !PLATFORM(QT) // strftime() we are using does not support # static const char* const formatStrings[] = { "%c", "%x", "%X" }; #else static const char* const formatStrings[] = { "%#c", "%#x", "%X" }; #endif // Offset year if needed struct tm localTM = gdt; int year = gdt.year + 1900; bool yearNeedsOffset = year < 1900 || year > 2038; if (yearNeedsOffset) localTM.tm_year = equivalentYearForDST(year) - 1900; #if HAVE(LANGINFO_H) // We do not allow strftime to generate dates with 2-digits years, // both to avoid ambiguity, and a crash in strncpy, for years that // need offset. char* formatString = strdup(nl_langinfo(formats[format])); char* yPos = strchr(formatString, 'y'); if (yPos) *yPos = 'Y'; #endif // Do the formatting const int bufsize = 128; char timebuffer[bufsize]; #if HAVE(LANGINFO_H) size_t ret = strftime(timebuffer, bufsize, formatString, &localTM); free(formatString); #else size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM); #endif if (ret == 0) return jsEmptyString(exec); // Copy original into the buffer if (yearNeedsOffset && format != LocaleTime) { static const int yearLen = 5; // FIXME will be a problem in the year 10,000 char yearString[yearLen]; snprintf(yearString, yearLen, "%d", localTM.tm_year + 1900); char* yearLocation = strstr(timebuffer, yearString); snprintf(yearString, yearLen, "%d", year); strncpy(yearLocation, yearString, yearLen - 1); } return jsNontrivialString(exec, timebuffer); }
void initializeDates() { #if !ASSERT_DISABLED static bool alreadyInitialized; ASSERT(!alreadyInitialized); alreadyInitialized = true; #endif equivalentYearForDST(2000); // Need to call once to initialize a static used in this function. }
// Get the DST offset, given a time in UTC static double getDSTOffset(double ms) { // On Mac OS X, the call to localtime (see getDSTOffsetSimple) 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 equvalentYear = equivalentYearForDST(year); if (year != equvalentYear) { int day = dateToDayInYear(equvalentYear, msToMonth(ms), msToDayInMonth(ms)); ms = (day * msPerDay) + msToMilliseconds(ms); } return getDSTOffsetSimple(ms / msPerSecond); }
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 }
// 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 }
// Get the DST offset, given a time in UTC static double calculateDSTOffset(double ms, double utcOffset) { // On Mac OS X, the call to localtime (see calculateDSTOffsetSimple) 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); } return calculateDSTOffsetSimple(ms / msPerSecond, utcOffset); }
static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, LocaleDateTimeFormat format) { #if OS(WINDOWS) SYSTEMTIME systemTime; memset(&systemTime, 0, sizeof(systemTime)); systemTime.wYear = gdt.year(); systemTime.wMonth = gdt.month() + 1; systemTime.wDay = gdt.monthDay(); systemTime.wDayOfWeek = gdt.weekDay(); systemTime.wHour = gdt.hour(); systemTime.wMinute = gdt.minute(); systemTime.wSecond = gdt.second(); Vector<UChar, 128> buffer; size_t length = 0; if (format == LocaleDate) { buffer.resize(GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &systemTime, 0, 0, 0)); length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &systemTime, 0, buffer.data(), buffer.size()); } else if (format == LocaleTime) { buffer.resize(GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systemTime, 0, 0, 0)); length = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systemTime, 0, buffer.data(), buffer.size()); } else if (format == LocaleDateAndTime) { buffer.resize(GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &systemTime, 0, 0, 0) + GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systemTime, 0, 0, 0)); length = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &systemTime, 0, buffer.data(), buffer.size()); if (length) { buffer[length - 1] = ' '; length += GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systemTime, 0, buffer.data() + length, buffer.size() - length); } } else RELEASE_ASSERT_NOT_REACHED(); // Remove terminating null character. if (length) length--; return jsNontrivialString(exec, String(buffer.data(), length)); #else // OS(WINDOWS) #if HAVE(LANGINFO_H) static const nl_item formats[] = { D_T_FMT, D_FMT, T_FMT }; #else static const char* const formatStrings[] = { "%#c", "%#x", "%X" }; #endif // Offset year if needed struct tm localTM = gdt; int year = gdt.year(); bool yearNeedsOffset = year < 1900 || year > 2038; if (yearNeedsOffset) localTM.tm_year = equivalentYearForDST(year) - 1900; #if HAVE(LANGINFO_H) // We do not allow strftime to generate dates with 2-digits years, // both to avoid ambiguity, and a crash in strncpy, for years that // need offset. char* formatString = strdup(nl_langinfo(formats[format])); char* yPos = strchr(formatString, 'y'); if (yPos) *yPos = 'Y'; #endif // Do the formatting const int bufsize = 128; char timebuffer[bufsize]; #if HAVE(LANGINFO_H) size_t ret = strftime(timebuffer, bufsize, formatString, &localTM); free(formatString); #else size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM); #endif if (ret == 0) return jsEmptyString(exec); // Copy original into the buffer if (yearNeedsOffset && format != LocaleTime) { static const int yearLen = 5; // FIXME will be a problem in the year 10,000 char yearString[yearLen]; snprintf(yearString, yearLen, "%d", localTM.tm_year + 1900); char* yearLocation = strstr(timebuffer, yearString); snprintf(yearString, yearLen, "%d", year); strncpy(yearLocation, yearString, yearLen - 1); } // Convert multi-byte result to UNICODE. // If __STDC_ISO_10646__ is defined, wide character represents // UTF-16 (or UTF-32) code point. In most modern Unix like system // (e.g. Linux with glibc 2.2 and above) the macro is defined, // and wide character represents UTF-32 code point. // Here we static_cast potential UTF-32 to UTF-16, it should be // safe because date and (or) time related characters in different languages // should be in UNICODE BMP. If mbstowcs fails, we just fall // back on using multi-byte result as-is. #ifdef __STDC_ISO_10646__ UChar buffer[bufsize]; wchar_t tempbuffer[bufsize]; size_t length = mbstowcs(tempbuffer, timebuffer, bufsize - 1); if (length != static_cast<size_t>(-1)) { for (size_t i = 0; i < length; ++i) buffer[i] = static_cast<UChar>(tempbuffer[i]); return jsNontrivialString(exec, String(buffer, length)); } #endif return jsNontrivialString(exec, timebuffer); #endif // OS(WINDOWS) }
static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, LocaleDateTimeFormat format) { #if HAVE(LANGINFO_H) static const nl_item formats[] = { D_T_FMT, D_FMT, T_FMT }; #elif (OS(WINCE) && !PLATFORM(QT)) || OS(SYMBIAN) // strftime() does not support '#' on WinCE or Symbian static const char* const formatStrings[] = { "%c", "%x", "%X" }; #else static const char* const formatStrings[] = { "%#c", "%#x", "%X" }; #endif // Offset year if needed struct tm localTM = gdt; int year = gdt.year + 1900; bool yearNeedsOffset = year < 1900 || year > 2038; if (yearNeedsOffset) localTM.tm_year = equivalentYearForDST(year) - 1900; #if HAVE(LANGINFO_H) // We do not allow strftime to generate dates with 2-digits years, // both to avoid ambiguity, and a crash in strncpy, for years that // need offset. char* formatString = strdup(nl_langinfo(formats[format])); char* yPos = strchr(formatString, 'y'); if (yPos) *yPos = 'Y'; #endif // Do the formatting const int bufsize = 128; char timebuffer[bufsize]; #if HAVE(LANGINFO_H) size_t ret = strftime(timebuffer, bufsize, formatString, &localTM); free(formatString); #else size_t ret = strftime(timebuffer, bufsize, formatStrings[format], &localTM); #endif if (ret == 0) return jsEmptyString(exec); // Copy original into the buffer if (yearNeedsOffset && format != LocaleTime) { static const int yearLen = 5; // FIXME will be a problem in the year 10,000 char yearString[yearLen]; snprintf(yearString, yearLen, "%d", localTM.tm_year + 1900); char* yearLocation = strstr(timebuffer, yearString); snprintf(yearString, yearLen, "%d", year); strncpy(yearLocation, yearString, yearLen - 1); } // Convert multi-byte result to UNICODE. // If __STDC_ISO_10646__ is defined, wide character represents // UTF-16 (or UTF-32) code point. In most modern Unix like system // (e.g. Linux with glibc 2.2 and above) the macro is defined, // and wide character represents UTF-32 code point. // Here we static_cast potential UTF-32 to UTF-16, it should be // safe because date and (or) time related characters in different languages // should be in UNICODE BMP. If mbstowcs fails, we just fall // back on using multi-byte result as-is. #ifdef __STDC_ISO_10646__ UChar buffer[bufsize]; wchar_t tempbuffer[bufsize]; size_t length = mbstowcs(tempbuffer, timebuffer, bufsize - 1); if (length != static_cast<size_t>(-1)) { for (size_t i = 0; i < length; ++i) buffer[i] = static_cast<UChar>(tempbuffer[i]); return jsNontrivialString(exec, UString(buffer, length)); } #endif return jsNontrivialString(exec, timebuffer); }