source: trunk/src/script/utils/qscriptdate.cpp@ 769

Last change on this file since 769 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

  • Property svn:eol-style set to native
File size: 8.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtScript module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL-ONLY$
10** GNU Lesser General Public License Usage
11** This file may be used under the terms of the GNU Lesser
12** General Public License version 2.1 as published by the Free Software
13** Foundation and appearing in the file LICENSE.LGPL included in the
14** packaging of this file. Please review the following information to
15** ensure the GNU Lesser General Public License version 2.1 requirements
16** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17**
18** If you have questions regarding the use of this file, please contact
19** Nokia at [email protected].
20** $QT_END_LICENSE$
21**
22****************************************************************************/
23
24#include "qscriptdate_p.h"
25
26#include <QtCore/qnumeric.h>
27#include <QtCore/qstringlist.h>
28
29#include <math.h>
30
31#ifndef Q_WS_WIN
32# include <time.h>
33# include <sys/time.h>
34#else
35# include <windows.h>
36#endif
37
38QT_BEGIN_NAMESPACE
39
40namespace QScript {
41
42qsreal ToInteger(qsreal n);
43
44static const qsreal HoursPerDay = 24.0;
45static const qsreal MinutesPerHour = 60.0;
46static const qsreal SecondsPerMinute = 60.0;
47static const qsreal msPerSecond = 1000.0;
48static const qsreal msPerMinute = 60000.0;
49static const qsreal msPerHour = 3600000.0;
50static const qsreal msPerDay = 86400000.0;
51
52static qsreal LocalTZA = 0.0; // initialized at startup
53
54static inline qsreal TimeWithinDay(qsreal t)
55{
56 qsreal r = ::fmod(t, msPerDay);
57 return (r >= 0) ? r : r + msPerDay;
58}
59
60static inline int HourFromTime(qsreal t)
61{
62 int r = int(::fmod(::floor(t / msPerHour), HoursPerDay));
63 return (r >= 0) ? r : r + int(HoursPerDay);
64}
65
66static inline int MinFromTime(qsreal t)
67{
68 int r = int(::fmod(::floor(t / msPerMinute), MinutesPerHour));
69 return (r >= 0) ? r : r + int(MinutesPerHour);
70}
71
72static inline int SecFromTime(qsreal t)
73{
74 int r = int(::fmod(::floor(t / msPerSecond), SecondsPerMinute));
75 return (r >= 0) ? r : r + int(SecondsPerMinute);
76}
77
78static inline int msFromTime(qsreal t)
79{
80 int r = int(::fmod(t, msPerSecond));
81 return (r >= 0) ? r : r + int(msPerSecond);
82}
83
84static inline qsreal Day(qsreal t)
85{
86 return ::floor(t / msPerDay);
87}
88
89static inline qsreal DaysInYear(qsreal y)
90{
91 if (::fmod(y, 4))
92 return 365;
93
94 else if (::fmod(y, 100))
95 return 366;
96
97 else if (::fmod(y, 400))
98 return 365;
99
100 return 366;
101}
102
103static inline qsreal DayFromYear(qsreal y)
104{
105 return 365 * (y - 1970)
106 + ::floor((y - 1969) / 4)
107 - ::floor((y - 1901) / 100)
108 + ::floor((y - 1601) / 400);
109}
110
111static inline qsreal TimeFromYear(qsreal y)
112{
113 return msPerDay * DayFromYear(y);
114}
115
116static inline qsreal YearFromTime(qsreal t)
117{
118 int y = 1970;
119 y += (int) ::floor(t / (msPerDay * 365.2425));
120
121 qsreal t2 = TimeFromYear(y);
122 return (t2 > t) ? y - 1 : ((t2 + msPerDay * DaysInYear(y)) <= t) ? y + 1 : y;
123}
124
125static inline bool InLeapYear(qsreal t)
126{
127 qsreal x = DaysInYear(YearFromTime(t));
128 if (x == 365)
129 return 0;
130
131 Q_ASSERT (x == 366);
132 return 1;
133}
134
135static inline qsreal DayWithinYear(qsreal t)
136{
137 return Day(t) - DayFromYear(YearFromTime(t));
138}
139
140static inline qsreal MonthFromTime(qsreal t)
141{
142 qsreal d = DayWithinYear(t);
143 qsreal l = InLeapYear(t);
144
145 if (d < 31.0)
146 return 0;
147
148 else if (d < 59.0 + l)
149 return 1;
150
151 else if (d < 90.0 + l)
152 return 2;
153
154 else if (d < 120.0 + l)
155 return 3;
156
157 else if (d < 151.0 + l)
158 return 4;
159
160 else if (d < 181.0 + l)
161 return 5;
162
163 else if (d < 212.0 + l)
164 return 6;
165
166 else if (d < 243.0 + l)
167 return 7;
168
169 else if (d < 273.0 + l)
170 return 8;
171
172 else if (d < 304.0 + l)
173 return 9;
174
175 else if (d < 334.0 + l)
176 return 10;
177
178 else if (d < 365.0 + l)
179 return 11;
180
181 return qSNaN(); // ### assert?
182}
183
184static inline qsreal DateFromTime(qsreal t)
185{
186 int m = (int) ToInteger(MonthFromTime(t));
187 qsreal d = DayWithinYear(t);
188 qsreal l = InLeapYear(t);
189
190 switch (m) {
191 case 0: return d + 1.0;
192 case 1: return d - 30.0;
193 case 2: return d - 58.0 - l;
194 case 3: return d - 89.0 - l;
195 case 4: return d - 119.0 - l;
196 case 5: return d - 150.0 - l;
197 case 6: return d - 180.0 - l;
198 case 7: return d - 211.0 - l;
199 case 8: return d - 242.0 - l;
200 case 9: return d - 272.0 - l;
201 case 10: return d - 303.0 - l;
202 case 11: return d - 333.0 - l;
203 }
204
205 return qSNaN(); // ### assert
206}
207
208static inline qsreal WeekDay(qsreal t)
209{
210 qsreal r = ::fmod (Day(t) + 4.0, 7.0);
211 return (r >= 0) ? r : r + 7.0;
212}
213
214
215static inline qsreal MakeTime(qsreal hour, qsreal min, qsreal sec, qsreal ms)
216{
217 return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * msPerSecond + ms;
218}
219
220static inline qsreal DayFromMonth(qsreal month, qsreal leap)
221{
222 switch ((int) month) {
223 case 0: return 0;
224 case 1: return 31.0;
225 case 2: return 59.0 + leap;
226 case 3: return 90.0 + leap;
227 case 4: return 120.0 + leap;
228 case 5: return 151.0 + leap;
229 case 6: return 181.0 + leap;
230 case 7: return 212.0 + leap;
231 case 8: return 243.0 + leap;
232 case 9: return 273.0 + leap;
233 case 10: return 304.0 + leap;
234 case 11: return 334.0 + leap;
235 }
236
237 return qSNaN(); // ### assert?
238}
239
240static qsreal MakeDay(qsreal year, qsreal month, qsreal day)
241{
242 year += ::floor(month / 12.0);
243
244 month = ::fmod(month, 12.0);
245 if (month < 0)
246 month += 12.0;
247
248 qsreal t = TimeFromYear(year);
249 qsreal leap = InLeapYear(t);
250
251 day += ::floor(t / msPerDay);
252 day += DayFromMonth(month, leap);
253
254 return day - 1;
255}
256
257static inline qsreal MakeDate(qsreal day, qsreal time)
258{
259 return day * msPerDay + time;
260}
261
262static inline qsreal DaylightSavingTA(double t)
263{
264#ifndef Q_WS_WIN
265 long int tt = (long int)(t / msPerSecond);
266 struct tm *tmtm = localtime((const time_t*)&tt);
267 if (! tmtm)
268 return 0;
269 return (tmtm->tm_isdst > 0) ? msPerHour : 0;
270#else
271 Q_UNUSED(t);
272 /// ### implement me
273 return 0;
274#endif
275}
276
277static inline qsreal LocalTime(qsreal t)
278{
279 return t + LocalTZA + DaylightSavingTA(t);
280}
281
282static inline qsreal UTC(qsreal t)
283{
284 return t - LocalTZA - DaylightSavingTA(t - LocalTZA);
285}
286
287static inline qsreal TimeClip(qsreal t)
288{
289 if (! qIsFinite(t) || fabs(t) > 8.64e15)
290 return qSNaN();
291 return ToInteger(t);
292}
293
294static qsreal getLocalTZA()
295{
296#ifndef Q_WS_WIN
297 struct tm* t;
298 time_t curr;
299 time(&curr);
300 t = localtime(&curr);
301 time_t locl = mktime(t);
302 t = gmtime(&curr);
303 time_t globl = mktime(t);
304 return double(locl - globl) * 1000.0;
305#else
306 TIME_ZONE_INFORMATION tzInfo;
307 GetTimeZoneInformation(&tzInfo);
308 return -tzInfo.Bias * 60.0 * 1000.0;
309#endif
310}
311
312/*!
313 \internal
314
315 Converts the QDateTime \a dt to an ECMA Date value (in UTC form).
316*/
317qsreal FromDateTime(const QDateTime &dt)
318{
319 if (!dt.isValid())
320 return qSNaN();
321 if (!LocalTZA) // ### move
322 LocalTZA = getLocalTZA();
323 QDate date = dt.date();
324 QTime taim = dt.time();
325 int year = date.year();
326 int month = date.month() - 1;
327 int day = date.day();
328 int hours = taim.hour();
329 int mins = taim.minute();
330 int secs = taim.second();
331 int ms = taim.msec();
332 double t = MakeDate(MakeDay(year, month, day),
333 MakeTime(hours, mins, secs, ms));
334 if (dt.timeSpec() == Qt::LocalTime)
335 t = UTC(t);
336 return TimeClip(t);
337}
338
339/*!
340 \internal
341
342 Converts the ECMA Date value \tt (in UTC form) to QDateTime
343 according to \a spec.
344*/
345QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec)
346{
347 if (qIsNaN(t))
348 return QDateTime();
349 if (!LocalTZA) // ### move
350 LocalTZA = getLocalTZA();
351 if (spec == Qt::LocalTime)
352 t = LocalTime(t);
353 int year = int(YearFromTime(t));
354 int month = int(MonthFromTime(t) + 1);
355 int day = int(DateFromTime(t));
356 int hours = HourFromTime(t);
357 int mins = MinFromTime(t);
358 int secs = SecFromTime(t);
359 int ms = msFromTime(t);
360 return QDateTime(QDate(year, month, day), QTime(hours, mins, secs, ms), spec);
361}
362
363} // namespace QScript
364
365QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.