source: trunk/src/corelib/tools/qdatetime.cpp@ 651

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

trunk: Merged in qt 4.6.2 sources.

File size: 169.5 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 QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qplatformdefs.h"
43#include "private/qdatetime_p.h"
44
45#include "qdatastream.h"
46#include "qset.h"
47#include "qlocale.h"
48#include "qdatetime.h"
49#include "qregexp.h"
50#include "qdebug.h"
51#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
52#include <qt_windows.h>
53#endif
54#ifndef Q_WS_WIN
55#include <locale.h>
56#endif
57
58#include <time.h>
59#if defined(Q_OS_WINCE)
60#include "qfunctions_wince.h"
61#endif
62
63//#define QDATETIMEPARSER_DEBUG
64#if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM)
65# define QDTPDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__)
66# define QDTPDEBUGN qDebug
67#else
68# define QDTPDEBUG if (false) qDebug()
69# define QDTPDEBUGN if (false) qDebug
70#endif
71
72#if defined(Q_WS_MAC)
73#include <private/qcore_mac_p.h>
74#endif
75
76#if defined(Q_OS_SYMBIAN)
77#include <e32std.h>
78#endif
79
80QT_BEGIN_NAMESPACE
81
82enum {
83 FIRST_YEAR = -4713,
84 FIRST_MONTH = 1,
85 FIRST_DAY = 2, // ### Qt 5: make FIRST_DAY = 1, by support jd == 0 as valid
86 SECS_PER_DAY = 86400,
87 MSECS_PER_DAY = 86400000,
88 SECS_PER_HOUR = 3600,
89 MSECS_PER_HOUR = 3600000,
90 SECS_PER_MIN = 60,
91 MSECS_PER_MIN = 60000
92};
93
94static inline QDate fixedDate(int y, int m, int d)
95{
96 QDate result(y, m, 1);
97 result.setDate(y, m, qMin(d, result.daysInMonth()));
98 return result;
99}
100
101static uint julianDayFromDate(int year, int month, int day)
102{
103 if (year < 0)
104 ++year;
105
106 if (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day >= 15)))) {
107 // Gregorian calendar starting from October 15, 1582
108 // Algorithm from Henry F. Fliegel and Thomas C. Van Flandern
109 return (1461 * (year + 4800 + (month - 14) / 12)) / 4
110 + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12
111 - (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4
112 + day - 32075;
113 } else if (year < 1582 || (year == 1582 && (month < 10 || (month == 10 && day <= 4)))) {
114 // Julian calendar until October 4, 1582
115 // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
116 int a = (14 - month) / 12;
117 return (153 * (month + (12 * a) - 3) + 2) / 5
118 + (1461 * (year + 4800 - a)) / 4
119 + day - 32083;
120 } else {
121 // the day following October 4, 1582 is October 15, 1582
122 return 0;
123 }
124}
125
126static void getDateFromJulianDay(uint julianDay, int *year, int *month, int *day)
127{
128 int y, m, d;
129
130 if (julianDay >= 2299161) {
131 // Gregorian calendar starting from October 15, 1582
132 // This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern
133 qulonglong ell, n, i, j;
134 ell = qulonglong(julianDay) + 68569;
135 n = (4 * ell) / 146097;
136 ell = ell - (146097 * n + 3) / 4;
137 i = (4000 * (ell + 1)) / 1461001;
138 ell = ell - (1461 * i) / 4 + 31;
139 j = (80 * ell) / 2447;
140 d = ell - (2447 * j) / 80;
141 ell = j / 11;
142 m = j + 2 - (12 * ell);
143 y = 100 * (n - 49) + i + ell;
144 } else {
145 // Julian calendar until October 4, 1582
146 // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
147 julianDay += 32082;
148 int dd = (4 * julianDay + 3) / 1461;
149 int ee = julianDay - (1461 * dd) / 4;
150 int mm = ((5 * ee) + 2) / 153;
151 d = ee - (153 * mm + 2) / 5 + 1;
152 m = mm + 3 - 12 * (mm / 10);
153 y = dd - 4800 + (mm / 10);
154 if (y <= 0)
155 --y;
156 }
157 if (year)
158 *year = y;
159 if (month)
160 *month = m;
161 if (day)
162 *day = d;
163}
164
165
166static const char monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
167
168#ifndef QT_NO_TEXTDATE
169static const char * const qt_shortMonthNames[] = {
170 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
171 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
172#endif
173#ifndef QT_NO_DATESTRING
174static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0);
175#endif
176
177/*****************************************************************************
178 QDate member functions
179 *****************************************************************************/
180
181/*!
182 \since 4.5
183
184 \enum QDate::MonthNameType
185
186 This enum describes the types of the string representation used
187 for the month name.
188
189 \value DateFormat This type of name can be used for date-to-string formatting.
190 \value StandaloneFormat This type is used when you need to enumerate months or weekdays.
191 Usually standalone names are represented in singular forms with
192 capitalized first letter.
193*/
194
195/*!
196 \class QDate
197 \reentrant
198 \brief The QDate class provides date functions.
199
200
201 A QDate object contains a calendar date, i.e. year, month, and day
202 numbers, in the Gregorian calendar. (see \l{QDate G and J} {Use of
203 Gregorian and Julian Calendars} for dates prior to 15 October
204 1582). It can read the current date from the system clock. It
205 provides functions for comparing dates, and for manipulating
206 dates. For example, it is possible to add and subtract days,
207 months, and years to dates.
208
209 A QDate object is typically created either by giving the year,
210 month, and day numbers explicitly. Note that QDate interprets two
211 digit years as is, i.e., years 0 - 99. A QDate can also be
212 constructed with the static function currentDate(), which creates
213 a QDate object containing the system clock's date. An explicit
214 date can also be set using setDate(). The fromString() function
215 returns a QDate given a string and a date format which is used to
216 interpret the date within the string.
217
218 The year(), month(), and day() functions provide access to the
219 year, month, and day numbers. Also, dayOfWeek() and dayOfYear()
220 functions are provided. The same information is provided in
221 textual format by the toString(), shortDayName(), longDayName(),
222 shortMonthName(), and longMonthName() functions.
223
224 QDate provides a full set of operators to compare two QDate
225 objects where smaller means earlier, and larger means later.
226
227 You can increment (or decrement) a date by a given number of days
228 using addDays(). Similarly you can use addMonths() and addYears().
229 The daysTo() function returns the number of days between two
230 dates.
231
232 The daysInMonth() and daysInYear() functions return how many days
233 there are in this date's month and year, respectively. The
234 isLeapYear() function indicates whether a date is in a leap year.
235
236 \section1
237
238 \target QDate G and J
239 \section2 Use of Gregorian and Julian Calendars
240
241 QDate uses the Gregorian calendar in all locales, beginning
242 on the date 15 October 1582. For dates up to and including 4
243 October 1582, the Julian calendar is used. This means there is a
244 10-day gap in the internal calendar between the 4th and the 15th
245 of October 1582. When you use QDateTime for dates in that epoch,
246 the day after 4 October 1582 is 15 October 1582, and the dates in
247 the gap are invalid.
248
249 The Julian to Gregorian changeover date used here is the date when
250 the Gregorian calendar was first introduced, by Pope Gregory
251 XIII. That change was not universally accepted and some localities
252 only executed it at a later date (if at all). QDateTime
253 doesn't take any of these historical facts into account. If an
254 application must support a locale-specific dating system, it must
255 do so on its own, remembering to convert the dates using the
256 Julian day.
257
258 \section2 No Year 0
259
260 There is no year 0. Dates in that year are considered invalid. The
261 year -1 is the year "1 before Christ" or "1 before current era."
262 The day before 0001-01-01 is December 31st, 1 BCE.
263
264 \section2 Range of Valid Dates
265
266 The range of valid dates is from January 2nd, 4713 BCE, to
267 sometime in the year 11 million CE. The Julian Day returned by
268 QDate::toJulianDay() is a number in the contiguous range from 1 to
269 \e{overflow}, even across QDateTime's "date holes". It is suitable
270 for use in applications that must convert a QDateTime to a date in
271 another calendar system, e.g., Hebrew, Islamic or Chinese.
272
273 \sa QTime, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget
274*/
275
276/*!
277 \fn QDate::QDate()
278
279 Constructs a null date. Null dates are invalid.
280
281 \sa isNull(), isValid()
282*/
283
284/*!
285 Constructs a date with year \a y, month \a m and day \a d.
286
287 If the specified date is invalid, the date is not set and
288 isValid() returns false. A date before 2 January 4713 B.C. is
289 considered invalid.
290
291 \warning Years 0 to 99 are interpreted as is, i.e., years
292 0-99.
293
294 \sa isValid()
295*/
296
297QDate::QDate(int y, int m, int d)
298{
299 setDate(y, m, d);
300}
301
302
303/*!
304 \fn bool QDate::isNull() const
305
306 Returns true if the date is null; otherwise returns false. A null
307 date is invalid.
308
309 \note The behavior of this function is equivalent to isValid().
310
311 \sa isValid()
312*/
313
314
315/*!
316 Returns true if this date is valid; otherwise returns false.
317
318 \sa isNull()
319*/
320
321bool QDate::isValid() const
322{
323 return !isNull();
324}
325
326
327/*!
328 Returns the year of this date. Negative numbers indicate years
329 before 1 A.D. = 1 C.E., such that year -44 is 44 B.C.
330
331 \sa month(), day()
332*/
333
334int QDate::year() const
335{
336 int y;
337 getDateFromJulianDay(jd, &y, 0, 0);
338 return y;
339}
340
341/*!
342 Returns the number corresponding to the month of this date, using
343 the following convention:
344
345 \list
346 \i 1 = "January"
347 \i 2 = "February"
348 \i 3 = "March"
349 \i 4 = "April"
350 \i 5 = "May"
351 \i 6 = "June"