summaryrefslogtreecommitdiff
path: root/Source/WTF/wtf/DateMath.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WTF/wtf/DateMath.cpp')
-rw-r--r--Source/WTF/wtf/DateMath.cpp80
1 files changed, 57 insertions, 23 deletions
diff --git a/Source/WTF/wtf/DateMath.cpp b/Source/WTF/wtf/DateMath.cpp
index 654bd8d2d..1350e3040 100644
--- a/Source/WTF/wtf/DateMath.cpp
+++ b/Source/WTF/wtf/DateMath.cpp
@@ -121,18 +121,16 @@ static const int firstDayOfMonth[2][12] = {
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
};
-#if !OS(WINCE)
static inline void getLocalTime(const time_t* localTime, struct tm* localTM)
{
-#if COMPILER(MINGW)
- *localTM = *localtime(localTime);
-#elif COMPILER(MSVC)
+#if COMPILER(MSVC)
localtime_s(localTM, localTime);
-#else
+#elif HAVE(LOCALTIME_R)
localtime_r(localTime, localTM);
+#else
+ localtime_s(localTime, localTM);
#endif
}
-#endif
bool isLeapYear(int year)
{
@@ -166,7 +164,7 @@ static inline double daysFrom1970ToYear(int year)
const double yearsToExcludeBy100Rule = floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule;
const double yearsToAddBy400Rule = floor(yearMinusOne / 400.0) - leapDaysBefore1971By400Rule;
- return 365.0 * (year - 1970) + yearsToAddBy4Rule - yearsToExcludeBy100Rule + yearsToAddBy400Rule;
+ return 365.0 * (year - 1970.0) + yearsToAddBy4Rule - yearsToExcludeBy100Rule + yearsToAddBy400Rule;
}
double msToDays(double ms)
@@ -359,16 +357,56 @@ int equivalentYearForDST(int year)
int product = (quotient) * 28;
year += product;
- ASSERT((year >= minYear && year <= maxYear) || (product - year == static_cast<int>(std::numeric_limits<double>::quiet_NaN())));
return year;
}
+#if OS(WINDOWS)
+typedef BOOL(WINAPI* callGetTimeZoneInformationForYear_t)(USHORT, PDYNAMIC_TIME_ZONE_INFORMATION, LPTIME_ZONE_INFORMATION);
+
+static callGetTimeZoneInformationForYear_t timeZoneInformationForYearFunction()
+{
+ static callGetTimeZoneInformationForYear_t getTimeZoneInformationForYear = nullptr;
+
+ if (getTimeZoneInformationForYear)
+ return getTimeZoneInformationForYear;
+
+ HMODULE module = ::GetModuleHandleW(L"kernel32.dll");
+ if (!module)
+ return nullptr;
+
+ getTimeZoneInformationForYear = reinterpret_cast<callGetTimeZoneInformationForYear_t>(::GetProcAddress(module, "GetTimeZoneInformationForYear"));
+
+ return getTimeZoneInformationForYear;
+}
+#endif
+
static int32_t calculateUTCOffset()
{
#if OS(WINDOWS)
TIME_ZONE_INFORMATION timeZoneInformation;
- GetTimeZoneInformation(&timeZoneInformation);
- int32_t bias = timeZoneInformation.Bias + timeZoneInformation.StandardBias;
+ DWORD rc = 0;
+
+ if (callGetTimeZoneInformationForYear_t timeZoneFunction = timeZoneInformationForYearFunction()) {
+ // If available, use the Windows API call that takes into account the varying DST from
+ // year to year.
+ SYSTEMTIME systemTime;
+ ::GetSystemTime(&systemTime);
+ rc = timeZoneFunction(systemTime.wYear, nullptr, &timeZoneInformation);
+ if (rc == TIME_ZONE_ID_INVALID)
+ return 0;
+ } else {
+ rc = ::GetTimeZoneInformation(&timeZoneInformation);
+ if (rc == TIME_ZONE_ID_INVALID)
+ return 0;
+ }
+
+ int32_t bias = timeZoneInformation.Bias;
+
+ if (rc == TIME_ZONE_ID_DAYLIGHT)
+ bias += timeZoneInformation.DaylightBias;
+ else if (rc == TIME_ZONE_ID_STANDARD || rc == TIME_ZONE_ID_UNKNOWN)
+ bias += timeZoneInformation.StandardBias;
+
return -bias * 60 * 1000;
#else
time_t localTime = time(0);
@@ -424,16 +462,14 @@ static void UnixTimeToFileTime(time_t t, LPFILETIME pft)
*/
static double calculateDSTOffset(time_t localTime, double utcOffset)
{
-#if OS(WINCE)
- UNUSED_PARAM(localTime);
- UNUSED_PARAM(utcOffset);
- return 0;
-#elif OS(WINDOWS)
+#if OS(WINDOWS)
FILETIME utcFileTime;
UnixTimeToFileTime(localTime, &utcFileTime);
SYSTEMTIME utcSystemTime, localSystemTime;
- FileTimeToSystemTime(&utcFileTime, &utcSystemTime);
- SystemTimeToTzSpecificLocalTime(0, &utcSystemTime, &localSystemTime);
+ if (!::FileTimeToSystemTime(&utcFileTime, &utcSystemTime))
+ return 0;
+ if (!::SystemTimeToTzSpecificLocalTime(nullptr, &utcSystemTime, &localSystemTime))
+ return 0;
double offsetTime = (localTime * msPerSecond) + utcOffset;
@@ -524,12 +560,10 @@ void initializeDates()
static inline double ymdhmsToSeconds(int year, long mon, long day, long hour, long minute, double second)
{
- double days = (day - 32075)
- + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4)
- + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12
- - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4)
- - 2440588;
- return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second;
+ int mday = firstDayOfMonth[isLeapYear(year)][mon - 1];
+ double ydays = daysFrom1970ToYear(year);
+
+ return (second + minute * secondsPerMinute + hour * secondsPerHour + (mday + day - 1 + ydays) * secondsPerDay);
}
// We follow the recommendation of RFC 2822 to consider all