1/*
2 * Copyright (C) 2012, 2014 Patrick Gansterer <[email protected]>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "config.h"
26#include <wtf/GregorianDateTime.h>
27
28#include <wtf/DateMath.h>
29
30#if OS(WINDOWS)
31#include <windows.h>
32#else
33#include <time.h>
34#endif
35
36namespace WTF {
37
38GregorianDateTime::GregorianDateTime(double ms, LocalTimeOffset localTime)
39{
40 if (ms >= 0
41#if OS(WINDOWS) && CPU(X86)
42 // The VS Compiler for 32-bit builds generates a floating point error when attempting to cast
43 // from an infinity to a 64-bit integer. We leave this routine with the floating point error
44 // left in a register, causing undefined behavior in later floating point operations.
45 //
46 // To avoid this issue, we check for infinity here, and return false in that case.
47 && !std::isinf(ms)
48#endif
49 ) {
50 int64_t integer = static_cast<int64_t>(ms);
51 if (static_cast<double>(integer) == ms && integer <= maxECMAScriptTime) {
52 // Positive integer fast path.
53 WTF::TimeClippedPositiveMilliseconds timeClipped(integer);
54 const int year = msToYear(ms);
55 setSecond(msToSeconds(timeClipped));
56 setMinute(msToMinutes(timeClipped));
57 setHour(msToHours(timeClipped));
58 setWeekDay(msToWeekDay(timeClipped));
59 int yearDay = dayInYear(timeClipped, year);
60 bool leapYear = isLeapYear(year);
61 setYearDay(yearDay);
62 setMonthDay(dayInMonthFromDayInYear(yearDay, leapYear));
63 setMonth(monthFromDayInYear(yearDay, leapYear));
64 setYear(year);
65 setIsDST(localTime.isDST);
66 setUTCOffsetInMinute(localTime.offset / WTF::msPerMinute);
67 return;
68 }
69 }
70 const int year = msToYear(ms);
71 setSecond(msToSeconds(ms));
72 setMinute(msToMinutes(ms));
73 setHour(msToHours(ms));
74 setWeekDay(msToWeekDay(ms));
75 int yearDay = dayInYear(ms, year);
76 bool leapYear = isLeapYear(year);
77 setYearDay(yearDay);
78 setMonthDay(dayInMonthFromDayInYear(yearDay, leapYear));
79 setMonth(monthFromDayInYear(yearDay, leapYear));
80 setYear(year);
81 setIsDST(localTime.isDST);
82 setUTCOffsetInMinute(localTime.offset / WTF::msPerMinute);
83}
84
85void GregorianDateTime::setToCurrentLocalTime()
86{
87#if OS(WINDOWS)
88 SYSTEMTIME systemTime;
89 GetLocalTime(&systemTime);
90 TIME_ZONE_INFORMATION timeZoneInformation;
91 DWORD timeZoneId = GetTimeZoneInformation(&timeZoneInformation);
92
93 LONG bias = 0;
94 if (timeZoneId != TIME_ZONE_ID_INVALID) {
95 bias = timeZoneInformation.Bias;
96 if (timeZoneId == TIME_ZONE_ID_DAYLIGHT)
97 bias += timeZoneInformation.DaylightBias;
98 else if ((timeZoneId == TIME_ZONE_ID_STANDARD) || (timeZoneId == TIME_ZONE_ID_UNKNOWN))
99 bias += timeZoneInformation.StandardBias;
100 else
101 ASSERT(0);
102 }
103
104 m_year = systemTime.wYear;
105 m_month = systemTime.wMonth - 1;
106 m_monthDay = systemTime.wDay;
107 m_yearDay = dayInYear(m_year, m_month, m_monthDay);
108 m_weekDay = systemTime.wDayOfWeek;
109 m_hour = systemTime.wHour;
110 m_minute = systemTime.wMinute;
111 m_second = systemTime.wSecond;
112 m_utcOffsetInMinute = -bias;
113 m_isDST = timeZoneId == TIME_ZONE_ID_DAYLIGHT ? 1 : 0;
114#else
115 tm localTM;
116 time_t localTime = time(0);
117#if HAVE(LOCALTIME_R)
118 localtime_r(&localTime, &localTM);
119#else
120 localtime_s(&localTime, &localTM);
121#endif
122
123 m_year = localTM.tm_year + 1900;
124 m_month = localTM.tm_mon;
125 m_monthDay = localTM.tm_mday;
126 m_yearDay = localTM.tm_yday;
127 m_weekDay = localTM.tm_wday;
128 m_hour = localTM.tm_hour;
129 m_minute = localTM.tm_min;
130 m_second = localTM.tm_sec;
131 m_isDST = localTM.tm_isdst;
132#if HAVE(TM_GMTOFF)
133 m_utcOffsetInMinute = localTM.tm_gmtoff / secondsPerMinute;
134#else
135 m_utcOffsetInMinute = calculateLocalTimeOffset(localTime * msPerSecond).offset / msPerMinute;
136#endif
137#endif
138}
139
140} // namespace WTF
141