1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
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 #include <tz.h>
79 #endif
80 
81 QT_BEGIN_NAMESPACE
82 
83 enum {
84     FIRST_YEAR = -4713,
85     FIRST_MONTH = 1,
86     FIRST_DAY = 2,  // ### Qt 5: make FIRST_DAY = 1, by support jd == 0 as valid
87     SECS_PER_DAY = 86400,
88     MSECS_PER_DAY = 86400000,
89     SECS_PER_HOUR = 3600,
90     MSECS_PER_HOUR = 3600000,
91     SECS_PER_MIN = 60,
92     MSECS_PER_MIN = 60000,
93     JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromGregorianDate(1970, 1, 1)
94 };
95 
fixedDate(int y,int m,int d)96 static inline QDate fixedDate(int y, int m, int d)
97 {
98     QDate result(y, m, 1);
99     result.setDate(y, m, qMin(d, result.daysInMonth()));
100     return result;
101 }
102 
julianDayFromGregorianDate(int year,int month,int day)103 static inline uint julianDayFromGregorianDate(int year, int month, int day)
104 {
105     // Gregorian calendar starting from October 15, 1582
106     // Algorithm from Henry F. Fliegel and Thomas C. Van Flandern
107     return (1461 * (year + 4800 + (month - 14) / 12)) / 4
108            + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12
109            - (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4
110            + day - 32075;
111 }
112 
julianDayFromDate(int year,int month,int day)113 static uint julianDayFromDate(int year, int month, int day)
114 {
115     if (year < 0)
116         ++year;
117 
118     if (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day >= 15)))) {
119         return julianDayFromGregorianDate(year, month, day);
120     } else if (year < 1582 || (year == 1582 && (month < 10 || (month == 10 && day <= 4)))) {
121         // Julian calendar until October 4, 1582
122         // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
123         int a = (14 - month) / 12;
124         return (153 * (month + (12 * a) - 3) + 2) / 5
125                + (1461 * (year + 4800 - a)) / 4
126                + day - 32083;
127     } else {
128         // the day following October 4, 1582 is October 15, 1582
129         return 0;
130     }
131 }
132 
getDateFromJulianDay(uint julianDay,int * year,int * month,int * day)133 static void getDateFromJulianDay(uint julianDay, int *year, int *month, int *day)
134 {
135     int y, m, d;
136 
137     if (julianDay >= 2299161) {
138         // Gregorian calendar starting from October 15, 1582
139         // This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern
140         qulonglong ell, n, i, j;
141         ell = qulonglong(julianDay) + 68569;
142         n = (4 * ell) / 146097;
143         ell = ell - (146097 * n + 3) / 4;
144         i = (4000 * (ell + 1)) / 1461001;
145         ell = ell - (1461 * i) / 4 + 31;
146         j = (80 * ell) / 2447;
147         d = ell - (2447 * j) / 80;
148         ell = j / 11;
149         m = j + 2 - (12 * ell);
150         y = 100 * (n - 49) + i + ell;
151     } else {
152         // Julian calendar until October 4, 1582
153         // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
154         julianDay += 32082;
155         int dd = (4 * julianDay + 3) / 1461;
156         int ee = julianDay - (1461 * dd) / 4;
157         int mm = ((5 * ee) + 2) / 153;
158         d = ee - (153 * mm + 2) / 5 + 1;
159         m = mm + 3 - 12 * (mm / 10);
160         y = dd - 4800 + (mm / 10);
161         if (y <= 0)
162             --y;
163     }
164     if (year)
165         *year = y;
166     if (month)
167         *month = m;
168     if (day)
169         *day = d;
170 }
171 
172 
173 static const char monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
174 
175 #ifndef QT_NO_TEXTDATE
176 static const char * const qt_shortMonthNames[] = {
177     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
178     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
179 #endif
180 #ifndef QT_NO_DATESTRING
181 static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0);
182 #endif
183 
184 /*****************************************************************************
185   QDate member functions
186  *****************************************************************************/
187 
188 /*!
189     \since 4.5
190 
191     \enum QDate::MonthNameType
192 
193     This enum describes the types of the string representation used
194     for the month name.
195 
196     \value DateFormat This type of name can be used for date-to-string formatting.
197     \value StandaloneFormat This type is used when you need to enumerate months or weekdays.
198            Usually standalone names are represented in singular forms with
199            capitalized first letter.
200 */
201 
202 /*!
203     \class QDate
204     \reentrant
205     \brief The QDate class provides date functions.
206 
207 
208     A QDate object contains a calendar date, i.e. year, month, and day
209     numbers, in the Gregorian calendar. (see \l{QDate G and J} {Use of
210     Gregorian and Julian Calendars} for dates prior to 15 October
211     1582). It can read the current date from the system clock. It
212     provides functions for comparing dates, and for manipulating
213     dates. For example, it is possible to add and subtract days,
214     months, and years to dates.
215 
216     A QDate object is typically created either by giving the year,
217     month, and day numbers explicitly. Note that QDate interprets two
218     digit years as is, i.e., years 0 - 99. A QDate can also be
219     constructed with the static function currentDate(), which creates
220     a QDate object containing the system clock's date.  An explicit
221     date can also be set using setDate(). The fromString() function
222     returns a QDate given a string and a date format which is used to
223     interpret the date within the string.
224 
225     The year(), month(), and day() functions provide access to the
226     year, month, and day numbers. Also, dayOfWeek() and dayOfYear()
227     functions are provided. The same information is provided in
228     textual format by the toString(), shortDayName(), longDayName(),
229     shortMonthName(), and longMonthName() functions.
230 
231     QDate provides a full set of operators to compare two QDate
232     objects where smaller means earlier, and larger means later.
233 
234     You can increment (or decrement) a date by a given number of days
235     using addDays(). Similarly you can use addMonths() and addYears().
236     The daysTo() function returns the number of days between two
237     dates.
238 
239     The daysInMonth() and daysInYear() functions return how many days
240     there are in this date's month and year, respectively. The
241     isLeapYear() function indicates whether a date is in a leap year.
242 
243     \section1
244 
245     \target QDate G and J
246     \section2 Use of Gregorian and Julian Calendars
247 
248     QDate uses the Gregorian calendar in all locales, beginning
249     on the date 15 October 1582. For dates up to and including 4
250     October 1582, the Julian calendar is used.  This means there is a
251     10-day gap in the internal calendar between the 4th and the 15th
252     of October 1582. When you use QDateTime for dates in that epoch,
253     the day after 4 October 1582 is 15 October 1582, and the dates in
254     the gap are invalid.
255 
256     The Julian to Gregorian changeover date used here is the date when
257     the Gregorian calendar was first introduced, by Pope Gregory
258     XIII. That change was not universally accepted and some localities
259     only executed it at a later date (if at all).  QDateTime
260     doesn't take any of these historical facts into account. If an
261     application must support a locale-specific dating system, it must
262     do so on its own, remembering to convert the dates using the
263     Julian day.
264 
265     \section2 No Year 0
266 
267     There is no year 0. Dates in that year are considered invalid. The
268     year -1 is the year "1 before Christ" or "1 before current era."
269     The day before 0001-01-01 is December 31st, 1 BCE.
270 
271     \section2 Range of Valid Dates
272 
273     The range of valid dates is from January 2nd, 4713 BCE, to
274     sometime in the year 11 million CE. The Julian Day returned by
275     QDate::toJulianDay() is a number in the contiguous range from 1 to
276     \e{overflow}, even across QDateTime's "date holes". It is suitable
277     for use in applications that must convert a QDateTime to a date in
278     another calendar system, e.g., Hebrew, Islamic or Chinese.
279 
280     \sa QTime, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget
281 */
282 
283 /*!
284     \fn QDate::QDate()
285 
286     Constructs a null date. Null dates are invalid.
287 
288     \sa isNull(), isValid()
289 */
290 
291 /*!
292     Constructs a date with year \a y, month \a m and day \a d.
293 
294     If the specified date is invalid, the date is not set and
295     isValid() returns false. A date before 2 January 4713 B.C. is
296     considered invalid.
297 
298     \warning Years 0 to 99 are interpreted as is, i.e., years
299              0-99.
300 
301     \sa isValid()
302 */
303 
QDate(int y,int m,int d)304 QDate::QDate(int y, int m, int d)
305 {
306     setDate(y, m, d);
307 }
308 
309 
310 /*!
311     \fn bool QDate::isNull() const
312 
313     Returns true if the date is null; otherwise returns false. A null
314     date is invalid.
315 
316     \note The behavior of this function is equivalent to isValid().
317 
318     \sa isValid()
319 */
320 
321 
322 /*!
323     Returns true if this date is valid; otherwise returns false.
324 
325     \sa isNull()
326 */
327 
isValid() const328 bool QDate::isValid() const
329 {
330     return !isNull();
331 }
332 
333 
334 /*!
335     Returns the year of this date. Negative numbers indicate years
336     before 1 A.D. = 1 C.E., such that year -44 is 44 B.C.
337 
338     \sa month(), day()
339 */
340 
year() const341 int QDate::year() const
342 {
343     int y;
344     getDateFromJulianDay(jd, &y, 0, 0);
345     return y;
346 }
347 
348 /*!
349     Returns the number corresponding to the month of this date, using
350     the following convention:
351 
352     \list
353     \i 1 = "January"
354     \i 2 = "February"
355     \i 3 = "March"
356     \i 4 = "April"
357     \i 5 = "May"
358     \i 6 = "June"
359     \i 7 = "July"
360     \i 8 = "August"
361     \i 9 = "September"
362     \i 10 = "October"
363     \i 11 = "November"
364     \i 12 = "December"
365     \endlist
366 
367     \sa year(), day()
368 */
369 
month() const370 int QDate::month() const
371 {
372     int m;
373     getDateFromJulianDay(jd, 0, &m, 0);
374     return m;
375 }
376 
377 /*!
378     Returns the day of the month (1 to 31) of this date.
379 
380     \sa year(), month(), dayOfWeek()
381 */
382 
day() const383 int QDate::day() const
384 {
385     int d;
386     getDateFromJulianDay(jd, 0, 0, &d);
387     return d;
388 }
389 
390 /*!
391     Returns the weekday (1 = Monday to 7 = Sunday) for this date.
392 
393     \sa day(), dayOfYear(), Qt::DayOfWeek
394 */
395 
dayOfWeek() const396 int QDate::dayOfWeek() const
397 {
398     return (jd % 7) + 1;
399 }
400 
401 /*!
402     Returns the day of the year (1 to 365 or 366 on leap years) for
403     this date.
404 
405     \sa day(), dayOfWeek()
406 */
407 
dayOfYear() const408 int QDate::dayOfYear() const
409 {
410     return jd - julianDayFromDate(year(), 1, 1) + 1;
411 }
412 
413 /*!
414     Returns the number of days in the month (28 to 31) for this date.
415 
416     \sa day(), daysInYear()
417 */
418 
daysInMonth() const419 int QDate::daysInMonth() const
420 {
421     int y, m, d;
422     getDateFromJulianDay(jd, &y, &m, &d);
423     if (m == 2 && isLeapYear(y))
424         return 29;
425     else
426         return monthDays[m];
427 }
428 
429 /*!
430     Returns the number of days in the year (365 or 366) for this date.
431 
432     \sa day(), daysInMonth()
433 */
434 
daysInYear() const435 int QDate::daysInYear() const
436 {
437     int y, m, d;
438     getDateFromJulianDay(jd, &y, &m, &d);
439     return isLeapYear(y) ? 366 : 365;
440 }
441 
442 /*!
443     Returns the week number (1 to 53), and stores the year in
444     *\a{yearNumber} unless \a yearNumber is null (the default).
445 
446     Returns 0 if the date is invalid.
447 
448     In accordance with ISO 8601, weeks start on Monday and the first
449     Thursday of a year is always in week 1 of that year. Most years
450     have 52 weeks, but some have 53.
451 
452     *\a{yearNumber} is not always the same as year(). For example, 1
453     January 2000 has week number 52 in the year 1999, and 31 December
454     2002 has week number 1 in the year 2003.
455 
456     \sa isValid()
457 */
458 
weekNumber(int * yearNumber) const459 int QDate::weekNumber(int *yearNumber) const
460 {
461     if (!isValid())
462         return 0;
463 
464     int year = QDate::year();
465     int yday = dayOfYear();
466     int wday = dayOfWeek();
467 
468     int week = (yday - wday + 10) / 7;
469 
470     if (week == 0) {
471         // last week of previous year
472         --year;
473         week = (yday + 365 + (QDate::isLeapYear(year) ? 1 : 0) - wday + 10) / 7;
474         Q_ASSERT(week == 52 || week == 53);
475     } else if (week == 53) {
476         // maybe first week of next year
477         int w = (yday - 365 - (QDate::isLeapYear(year + 1) ? 1 : 0) - wday + 10) / 7;
478         if (w > 0) {
479             ++year;
480             week = w;
481         }
482         Q_ASSERT(week == 53 || week == 1);
483     }
484 
485     if (yearNumber != 0)
486         *yearNumber = year;
487     return week;
488 }
489 
490 #ifndef QT_NO_TEXTDATE
491 /*!
492     \since 4.5
493 
494     Returns the short name of the \a month for the representation specified
495     by \a type.
496 
497     The months are enumerated using the following convention:
498 
499     \list
500     \i 1 = "Jan"
501     \i 2 = "Feb"
502     \i 3 = "Mar"
503     \i 4 = "Apr"
504     \i 5 = "May"
505     \i 6 = "Jun"
506     \i 7 = "Jul"
507     \i 8 = "Aug"
508     \i 9 = "Sep"
509     \i 10 = "Oct"
510     \i 11 = "Nov"
511     \i 12 = "Dec"
512     \endlist
513 
514     The month names will be localized according to the system's default
515     locale settings.
516 
517     \sa toString(), longMonthName(), shortDayName(), longDayName()
518 */
519 
shortMonthName(int month,QDate::MonthNameType type)520 QString QDate::shortMonthName(int month, QDate::MonthNameType type)
521 {
522     if (month < 1 || month > 12) {
523         month = 1;
524     }
525     switch (type) {
526     case QDate::DateFormat:
527         return QLocale::system().monthName(month, QLocale::ShortFormat);
528     case QDate::StandaloneFormat:
529         return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat);
530     default:
531         break;
532     }
533     return QString();
534 }
535 
536 /*!
537     Returns the short version of the name of the \a month. The
538     returned name is in normal type which can be used for date formatting.
539 
540     \sa toString(), longMonthName(), shortDayName(), longDayName()
541  */
542 
shortMonthName(int month)543 QString QDate::shortMonthName(int month)
544 {
545     return shortMonthName(month, QDate::DateFormat);
546 }
547 
548 /*!
549     \since 4.5
550 
551     Returns the long name of the \a month for the representation specified
552     by \a type.
553 
554     The months are enumerated using the following convention:
555 
556     \list
557     \i 1 = "January"
558     \i 2 = "February"
559     \i 3 = "March"
560     \i 4 = "April"
561     \i 5 = "May"
562     \i 6 = "June"
563     \i 7 = "July"
564     \i 8 = "August"
565     \i 9 = "September"
566     \i 10 = "October"
567     \i 11 = "November"
568     \i 12 = "December"
569     \endlist
570 
571     The month names will be localized according to the system's default
572     locale settings.
573 
574     \sa toString(), shortMonthName(), shortDayName(), longDayName()
575 */
576 
longMonthName(int month,MonthNameType type)577 QString QDate::longMonthName(int month, MonthNameType type)
578 {
579     if (month < 1 || month > 12) {
580         month = 1;
581     }
582     switch (type) {
583     case QDate::DateFormat:
584         return QLocale::system().monthName(month, QLocale::LongFormat);
585     case QDate::StandaloneFormat:
586         return QLocale::system().standaloneMonthName(month, QLocale::LongFormat);
587     default:
588         break;
589     }
590     return QString();
591 }
592 
593 /*!
594     Returns the long version of the name of the \a month. The
595     returned name is in normal type which can be used for date formatting.
596 
597     \sa toString(), shortMonthName(), shortDayName(), longDayName()
598  */
599 
longMonthName(int month)600 QString QDate::longMonthName(int month)
601 {
602     if (month < 1 || month > 12) {
603         month = 1;
604     }
605     return QLocale::system().monthName(month, QLocale::LongFormat);
606 }
607 
608 /*!
609     \since 4.5
610 
611     Returns the short name of the \a weekday for the representation specified
612     by \a type.
613 
614     The days are enumerated using the following convention:
615 
616     \list
617     \i 1 = "Mon"
618     \i 2 = "Tue"
619     \i 3 = "Wed"
620     \i 4 = "Thu"
621     \i 5 = "Fri"
622     \i 6 = "Sat"
623     \i 7 = "Sun"
624     \endlist
625 
626     The day names will be localized according to the system's default
627     locale settings.
628 
629     \sa toString(), shortMonthName(), longMonthName(), longDayName()
630 */
631 
shortDayName(int weekday,MonthNameType type)632 QString QDate::shortDayName(int weekday, MonthNameType type)
633 {
634     if (weekday < 1 || weekday > 7) {
635         weekday = 1;
636     }
637     switch (type) {
638     case QDate::DateFormat:
639         return QLocale::system().dayName(weekday, QLocale::ShortFormat);
640     case QDate::StandaloneFormat:
641         return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat);
642     default:
643         break;
644     }
645     return QString();
646 }
647 
648 /*!
649     Returns the short version of the name of the \a weekday. The
650     returned name is in normal type which can be used for date formatting.
651 
652     \sa toString(), longDayName(), shortMonthName(), longMonthName()
653  */
654 
shortDayName(int weekday)655 QString QDate::shortDayName(int weekday)
656 {
657     if (weekday < 1 || weekday > 7) {
658         weekday = 1;
659     }
660     return QLocale::system().dayName(weekday, QLocale::ShortFormat);
661 }
662 
663 /*!
664     \since 4.5
665 
666     Returns the long name of the \a weekday for the representation specified
667     by \a type.
668 
669     The days are enumerated using the following convention:
670 
671     \list
672     \i 1 = "Monday"
673     \i 2 = "Tuesday"
674     \i 3 = "Wednesday"
675     \i 4 = "Thursday"
676     \i 5 = "Friday"
677     \i 6 = "Saturday"
678     \i 7 = "Sunday"
679     \endlist
680 
681     The day names will be localized according to the system's default
682     locale settings.
683 
684     \sa toString(), shortDayName(), shortMonthName(), longMonthName()
685 */
686 
longDayName(int weekday,MonthNameType type)687 QString QDate::longDayName(int weekday, MonthNameType type)
688 {
689     if (weekday < 1 || weekday > 7) {
690         weekday = 1;
691     }
692     switch (type) {
693     case QDate::DateFormat:
694         return QLocale::system().dayName(weekday, QLocale::LongFormat);
695     case QDate::StandaloneFormat:
696         return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat);
697     default:
698         break;
699     }
700     return QLocale::system().dayName(weekday, QLocale::LongFormat);
701 }
702 
703 /*!
704     Returns the long version of the name of the \a weekday. The
705     returned name is in normal type which can be used for date formatting.
706 
707     \sa toString(), shortDayName(), shortMonthName(), longMonthName()
708  */
709 
longDayName(int weekday)710 QString QDate::longDayName(int weekday)
711 {
712     if (weekday < 1 || weekday > 7) {
713         weekday = 1;
714     }
715     return QLocale::system().dayName(weekday, QLocale::LongFormat);
716 }
717 #endif //QT_NO_TEXTDATE
718 
719 #ifndef QT_NO_DATESTRING
720 
721 /*!
722     \fn QString QDate::toString(Qt::DateFormat format) const
723 
724     \overload
725 
726     Returns the date as a string. The \a format parameter determines
727     the format of the string.
728 
729     If the \a format is Qt::TextDate, the string is formatted in
730     the default way. QDate::shortDayName() and QDate::shortMonthName()
731     are used to generate the string, so the day and month names will
732     be localized names using the default locale from the system. An
733     example of this formatting is "Sat May 20 1995".
734 
735     If the \a format is Qt::ISODate, the string format corresponds
736     to the ISO 8601 extended specification for representations of
737     dates and times, taking the form YYYY-MM-DD, where YYYY is the
738     year, MM is the month of the year (between 01 and 12), and DD is
739     the day of the month between 01 and 31.
740 
741     If the \a format is Qt::SystemLocaleShortDate or
742     Qt::SystemLocaleLongDate, the string format depends on the locale
743     settings of the system. Identical to calling
744     QLocale::system().toString(date, QLocale::ShortFormat) or
745     QLocale::system().toString(date, QLocale::LongFormat).
746 
747     If the \a format is Qt::DefaultLocaleShortDate or
748     Qt::DefaultLocaleLongDate, the string format depends on the
749     default application locale. This is the locale set with
750     QLocale::setDefault(), or the system locale if no default locale
751     has been set. Identical to calling QLocale().toString(date,
752     QLocale::ShortFormat) or QLocale().toString(date,
753     QLocale::LongFormat).
754 
755     If the date is invalid, an empty string will be returned.
756 
757     \warning The Qt::ISODate format is only valid for years in the
758     range 0 to 9999. This restriction may apply to locale-aware
759     formats as well, depending on the locale settings.
760 
761     \sa shortDayName(), shortMonthName()
762 */
toString(Qt::DateFormat f) const763 QString QDate::toString(Qt::DateFormat f) const
764 {
765     if (!isValid())
766         return QString();
767     int y, m, d;
768     getDateFromJulianDay(jd, &y, &m, &d);
769     switch (f) {
770     case Qt::SystemLocaleDate:
771     case Qt::SystemLocaleShortDate:
772     case Qt::SystemLocaleLongDate:
773         return QLocale::system().toString(*this, f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
774                                                                                : QLocale::ShortFormat);
775     case Qt::LocaleDate:
776     case Qt::DefaultLocaleShortDate:
777     case Qt::DefaultLocaleLongDate:
778         return QLocale().toString(*this, f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
779                                                                         : QLocale::ShortFormat);
780     default:
781 #ifndef QT_NO_TEXTDATE
782     case Qt::TextDate:
783         {
784             return QString::fromLatin1("%0 %1 %2 %3")
785                 .arg(shortDayName(dayOfWeek()))
786                 .arg(shortMonthName(m))
787                 .arg(d)
788                 .arg(y);
789         }
790 #endif
791     case Qt::ISODate:
792         {
793             if (year() < 0 || year() > 9999)
794                 return QString();
795             QString month(QString::number(m).rightJustified(2, QLatin1Char('0')));
796             QString day(QString::number(d).rightJustified(2, QLatin1Char('0')));
797             return QString::number(y) + QLatin1Char('-') + month + QLatin1Char('-') + day;
798         }
799     }
800 }
801 
802 /*!
803     Returns the date as a string. The \a format parameter determines
804     the format of the result string.
805 
806     These expressions may be used:
807 
808     \table
809     \header \i Expression \i Output
810     \row \i d \i the day as number without a leading zero (1 to 31)
811     \row \i dd \i the day as number with a leading zero (01 to 31)
812     \row \i ddd
813          \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
814             Uses QDate::shortDayName().
815     \row \i dddd
816          \i the long localized day name (e.g. 'Monday' to 'Sunday').
817             Uses QDate::longDayName().
818     \row \i M \i the month as number without a leading zero (1 to 12)
819     \row \i MM \i the month as number with a leading zero (01 to 12)
820     \row \i MMM
821          \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
822             Uses QDate::shortMonthName().
823     \row \i MMMM
824          \i the long localized month name (e.g. 'January' to 'December').
825             Uses QDate::longMonthName().
826     \row \i yy \i the year as two digit number (00 to 99)
827     \row \i yyyy \i the year as four digit number. If the year is negative,
828             a minus sign is prepended in addition.
829     \endtable
830 
831     All other input characters will be ignored. Any sequence of characters that
832     are enclosed in singlequotes will be treated as text and not be used as an
833     expression. Two consecutive singlequotes ("''") are replaced by a singlequote
834     in the output.
835 
836     Example format strings (assuming that the QDate is the 20 July
837     1969):
838 
839     \table
840     \header \o Format            \o Result
841     \row    \o dd.MM.yyyy        \o 20.07.1969
842     \row    \o ddd MMMM d yy     \o Sun July 20 69
843     \row    \o 'The day is' dddd \o The day is Sunday
844     \endtable
845 
846     If the datetime is invalid, an empty string will be returned.
847 
848     \warning The Qt::ISODate format is only valid for years in the
849     range 0 to 9999. This restriction may apply to locale-aware
850     formats as well, depending on the locale settings.
851 
852     \sa QDateTime::toString() QTime::toString()
853 
854 */
toString(const QString & format) const855 QString QDate::toString(const QString& format) const
856 {
857     if (year() > 9999)
858         return QString();
859     return fmtDateTime(format, 0, this);
860 }
861 #endif //QT_NO_DATESTRING
862 
863 /*!
864     \obsolete
865 
866     Sets the date's year \a y, month \a m, and day \a d.
867 
868     If \a y is in the range 0 to 99, it is interpreted as 1900 to
869     1999.
870 
871     Use setDate() instead.
872 */
873 
setYMD(int y,int m,int d)874 bool QDate::setYMD(int y, int m, int d)
875 {
876     if (uint(y) <= 99)
877         y += 1900;
878     return setDate(y, m, d);
879 }
880 
881 /*!
882     \since 4.2
883 
884     Sets the date's \a year, \a month, and \a day. Returns true if
885     the date is valid; otherwise returns false.
886 
887     If the specified date is invalid, the QDate object is set to be
888     invalid. Any date before 2 January 4713 B.C. is considered
889     invalid.
890 
891     \sa isValid()
892 */
setDate(int year,int month,int day)893 bool QDate::setDate(int year, int month, int day)
894 {
895     if (!isValid(year, month, day)) {
896         jd = 0;
897     } else {
898         jd = julianDayFromDate(year, month, day);
899     }
900     return jd != 0;
901 }
902 
903 /*!
904     \since 4.5
905 
906     Extracts the date's year, month, and day, and assigns them to
907     *\a year, *\a month, and *\a day. The pointers may be null.
908 
909     \sa year(), month(), day(), isValid()
910 */
getDate(int * year,int * month,int * day)911 void QDate::getDate(int *year, int *month, int *day)
912 {
913     getDateFromJulianDay(jd, year, month, day);
914 }
915 
916 /*!
917     Returns a QDate object containing a date \a ndays later than the
918     date of this object (or earlier if \a ndays is negative).
919 
920     \sa addMonths() addYears() daysTo()
921 */
922 
addDays(int ndays) const923 QDate QDate::addDays(int ndays) const
924 {
925     QDate d;
926     // this is basically "d.jd = jd + ndays" with checks for integer overflow
927     if (ndays >= 0)
928         d.jd = (jd + ndays >= jd) ? jd + ndays : 0;
929     else
930         d.jd = (jd + ndays < jd) ? jd + ndays : 0;
931     return d;
932 }
933 
934 /*!
935     Returns a QDate object containing a date \a nmonths later than the
936     date of this object (or earlier if \a nmonths is negative).
937 
938     \note If the ending day/month combination does not exist in the
939     resulting month/year, this function will return a date that is the
940     latest valid date.
941 
942     \warning QDate has a date hole around the days introducing the
943     Gregorian calendar (the days 5 to 14 October 1582, inclusive, do
944     not exist). If the calculation ends in one of those days, QDate
945     will return either October 4 or October 15.
946 
947     \sa addDays() addYears()
948 */
949 
addMonths(int nmonths) const950 QDate QDate::addMonths(int nmonths) const
951 {
952     if (!isValid())
953         return QDate();
954     if (!nmonths)
955         return *this;
956 
957     int old_y, y, m, d;
958     getDateFromJulianDay(jd, &y, &m, &d);
959     old_y = y;
960 
961     bool increasing = nmonths > 0;
962 
963     while (nmonths != 0) {
964         if (nmonths < 0 && nmonths + 12 <= 0) {
965             y--;
966             nmonths+=12;
967         } else if (nmonths < 0) {
968             m+= nmonths;
969             nmonths = 0;
970             if (m <= 0) {
971                 --y;
972                 m += 12;
973             }
974         } else if (nmonths - 12 >= 0) {
975             y++;
976             nmonths -= 12;
977         } else if (m == 12) {
978             y++;
979             m = 0;
980         } else {
981             m += nmonths;
982             nmonths = 0;
983             if (m > 12) {
984                 ++y;
985                 m -= 12;
986             }
987         }
988     }
989 
990     // was there a sign change?
991     if ((old_y > 0 && y <= 0) ||
992         (old_y < 0 && y >= 0))
993         // yes, adjust the date by +1 or -1 years
994         y += increasing ? +1 : -1;
995 
996     // did we end up in the Gregorian/Julian conversion hole?
997     if (y == 1582 && m == 10 && d > 4 && d < 15)
998         d = increasing ? 15 : 4;
999 
1000     return fixedDate(y, m, d);
1001 }
1002 
1003 /*!
1004     Returns a QDate object containing a date \a nyears later than the
1005     date of this object (or earlier if \a nyears is negative).
1006 
1007     \note If the ending day/month combination does not exist in the
1008     resulting year (i.e., if the date was Feb 29 and the final year is
1009     not a leap year), this function will return a date that is the
1010     latest valid date (that is, Feb 28).
1011 
1012     \sa addDays(), addMonths()
1013 */
1014 
addYears(int nyears) const1015 QDate QDate::addYears(int nyears) const
1016 {
1017     if (!isValid())
1018         return QDate();
1019 
1020     int y, m, d;
1021     getDateFromJulianDay(jd, &y, &m, &d);
1022 
1023     int old_y = y;
1024     y += nyears;
1025 
1026     // was there a sign change?
1027     if ((old_y > 0 && y <= 0) ||
1028         (old_y < 0 && y >= 0))
1029         // yes, adjust the date by +1 or -1 years
1030         y += nyears > 0 ? +1 : -1;
1031 
1032     return fixedDate(y, m, d);
1033 }
1034 
1035 /*!
1036     Returns the number of days from this date to \a d (which is
1037     negative if \a d is earlier than this date).
1038 
1039     Example:
1040     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 0
1041 
1042     \sa addDays()
1043 */
1044 
daysTo(const QDate & d) const1045 int QDate::daysTo(const QDate &d) const
1046 {
1047     return d.jd - jd;
1048 }
1049 
1050 
1051 /*!
1052     \fn bool QDate::operator==(const QDate &d) const
1053 
1054     Returns true if this date is equal to \a d; otherwise returns
1055     false.
1056 
1057 */
1058 
1059 /*!
1060     \fn bool QDate::operator!=(const QDate &d) const
1061 
1062     Returns true if this date is different from \a d; otherwise
1063     returns false.
1064 */
1065 
1066 /*!
1067     \fn bool QDate::operator<(const QDate &d) const
1068 
1069     Returns true if this date is earlier than \a d; otherwise returns
1070     false.
1071 */
1072 
1073 /*!
1074     \fn bool QDate::operator<=(const QDate &d) const
1075 
1076     Returns true if this date is earlier than or equal to \a d;
1077     otherwise returns false.
1078 */
1079 
1080 /*!
1081     \fn bool QDate::operator>(const QDate &d) const
1082 
1083     Returns true if this date is later than \a d; otherwise returns
1084     false.
1085 */
1086 
1087 /*!
1088     \fn bool QDate::operator>=(const QDate &d) const
1089 
1090     Returns true if this date is later than or equal to \a d;
1091     otherwise returns false.
1092 */
1093 
1094 /*!
1095     \fn QDate::currentDate()
1096     Returns the current date, as reported by the system clock.
1097 
1098     \sa QTime::currentTime(), QDateTime::currentDateTime()
1099 */
1100 
1101 #ifndef QT_NO_DATESTRING
1102 /*!
1103     \fn QDate QDate::fromString(const QString &string, Qt::DateFormat format)
1104 
1105     Returns the QDate represented by the \a string, using the
1106     \a format given, or an invalid date if the string cannot be
1107     parsed.
1108 
1109     Note for Qt::TextDate: It is recommended that you use the
1110     English short month names (e.g. "Jan"). Although localized month
1111     names can also be used, they depend on the user's locale settings.
1112 */
fromString(const QString & s,Qt::DateFormat f)1113 QDate QDate::fromString(const QString& s, Qt::DateFormat f)
1114 {
1115     if (s.isEmpty())
1116         return QDate();
1117 
1118     switch (f) {
1119     case Qt::ISODate:
1120         {
1121             int year(s.mid(0, 4).toInt());
1122             int month(s.mid(5, 2).toInt());
1123             int day(s.mid(8, 2).toInt());
1124             if (year && month && day)
1125                 return QDate(year, month, day);
1126         }
1127         break;
1128     case Qt::SystemLocaleDate:
1129     case Qt::SystemLocaleShortDate:
1130     case Qt::SystemLocaleLongDate:
1131         return fromString(s, QLocale::system().dateFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
1132                                                                                         : QLocale::ShortFormat));
1133     case Qt::LocaleDate:
1134     case Qt::DefaultLocaleShortDate:
1135     case Qt::DefaultLocaleLongDate:
1136         return fromString(s, QLocale().dateFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
1137                                                                                  : QLocale::ShortFormat));
1138     default:
1139 #ifndef QT_NO_TEXTDATE
1140     case Qt::TextDate: {
1141         QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
1142 
1143         if (parts.count() != 4) {
1144             return QDate();
1145         }
1146 
1147         QString monthName = parts.at(1);
1148         int month = -1;
1149         // Assume that English monthnames are the default
1150         for (int i = 0; i < 12; ++i) {
1151             if (monthName == QLatin1String(qt_shortMonthNames[i])) {
1152                 month = i + 1;
1153                 break;
1154             }
1155         }
1156         // If English names can't be found, search the localized ones
1157         if (month == -1) {
1158             for (int i = 1; i <= 12; ++i) {
1159                 if (monthName == QDate::shortMonthName(i)) {
1160                     month = i;
1161                     break;
1162                 }
1163             }
1164         }
1165         if (month < 1 || month > 12) {
1166             return QDate();
1167         }
1168 
1169         bool ok;
1170         int day = parts.at(2).toInt(&ok);
1171         if (!ok) {
1172             return QDate();
1173         }
1174 
1175         int year = parts.at(3).toInt(&ok);
1176         if (!ok) {
1177             return QDate();
1178         }
1179 
1180         return QDate(year, month, day);
1181     }
1182 #else
1183         break;
1184 #endif
1185     }
1186     return QDate();
1187 }
1188 
1189 /*!
1190     \fn QDate::fromString(const QString &string, const QString &format)
1191 
1192     Returns the QDate represented by the \a string, using the \a
1193     format given, or an invalid date if the string cannot be parsed.
1194 
1195     These expressions may be used for the format:
1196 
1197     \table
1198     \header \i Expression \i Output
1199     \row \i d \i The day as a number without a leading zero (1 to 31)
1200     \row \i dd \i The day as a number with a leading zero (01 to 31)
1201     \row \i ddd
1202          \i The abbreviated localized day name (e.g. 'Mon' to 'Sun').
1203             Uses QDate::shortDayName().
1204     \row \i dddd
1205          \i The long localized day name (e.g. 'Monday' to 'Sunday').
1206             Uses QDate::longDayName().
1207     \row \i M \i The month as a number without a leading zero (1 to 12)
1208     \row \i MM \i The month as a number with a leading zero (01 to 12)
1209     \row \i MMM
1210          \i The abbreviated localized month name (e.g. 'Jan' to 'Dec').
1211             Uses QDate::shortMonthName().
1212     \row \i MMMM
1213          \i The long localized month name (e.g. 'January' to 'December').
1214             Uses QDate::longMonthName().
1215     \row \i yy \i The year as two digit number (00 to 99)
1216     \row \i yyyy \i The year as four digit number. If the year is negative,
1217             a minus sign is prepended in addition.
1218     \endtable
1219 
1220     All other input characters will be treated as text. Any sequence
1221     of characters that are enclosed in single quotes will also be
1222     treated as text and will not be used as an expression. For example:
1223 
1224     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 1
1225 
1226     If the format is not satisfied, an invalid QDate is returned. The
1227     expressions that don't expect leading zeroes (d, M) will be
1228     greedy. This means that they will use two digits even if this
1229     will put them outside the accepted range of values and leaves too
1230     few digits for other sections. For example, the following format
1231     string could have meant January 30 but the M will grab two
1232     digits, resulting in an invalid date:
1233 
1234     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 2
1235 
1236     For any field that is not represented in the format the following
1237     defaults are used:
1238 
1239     \table
1240     \header \i Field  \i Default value
1241     \row    \i Year   \i 1900
1242     \row    \i Month  \i 1
1243     \row    \i Day    \i 1
1244     \endtable
1245 
1246     The following examples demonstrate the default values:
1247 
1248     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 3
1249 
1250     \sa QDateTime::fromString(), QTime::fromString(), QDate::toString(),
1251         QDateTime::toString(), QTime::toString()
1252 */
1253 
fromString(const QString & string,const QString & format)1254 QDate QDate::fromString(const QString &string, const QString &format)
1255 {
1256     QDate date;
1257 #ifndef QT_BOOTSTRAPPED
1258     QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
1259     if (dt.parseFormat(format))
1260         dt.fromString(string, &date, 0);
1261 #else
1262     Q_UNUSED(string);
1263     Q_UNUSED(format);
1264 #endif
1265     return date;
1266 }
1267 #endif // QT_NO_DATESTRING
1268 
1269 /*!
1270     \overload
1271 
1272     Returns true if the specified date (\a year, \a month, and \a
1273     day) is valid; otherwise returns false.
1274 
1275     Example:
1276     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 4
1277 
1278     \sa isNull(), setDate()
1279 */
1280 
isValid(int year,int month,int day)1281 bool QDate::isValid(int year, int month, int day)
1282 {
1283     if (year < FIRST_YEAR
1284         || (year == FIRST_YEAR &&
1285             (month < FIRST_MONTH
1286              || (month == FIRST_MONTH && day < FIRST_DAY)))
1287         || year == 0) // there is no year 0 in the Julian calendar
1288         return false;
1289 
1290     // passage from Julian to Gregorian calendar
1291     if (year == 1582 && month == 10 && day > 4 && day < 15)
1292         return 0;
1293 
1294     return (day > 0 && month > 0 && month <= 12) &&
1295            (day <= monthDays[month] || (day == 29 && month == 2 && isLeapYear(year)));
1296 }
1297 
1298 /*!
1299     \fn bool QDate::isLeapYear(int year)
1300 
1301     Returns true if the specified \a year is a leap year; otherwise
1302     returns false.
1303 */
1304 
isLeapYear(int y)1305 bool QDate::isLeapYear(int y)
1306 {
1307     if (y < 1582) {
1308         if ( y < 1) {  // No year 0 in Julian calendar, so -1, -5, -9 etc are leap years
1309             ++y;
1310         }
1311         return y % 4 == 0;
1312     } else {
1313         return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
1314     }
1315 }
1316 
1317 /*!
1318     \internal
1319 
1320     This function has a confusing name and shouldn't be part of the
1321     API anyway, since we have toJulian() and fromJulian().
1322     ### Qt 5: remove it
1323 */
gregorianToJulian(int y,int m,int d)1324 uint QDate::gregorianToJulian(int y, int m, int d)
1325 {
1326     return julianDayFromDate(y, m, d);
1327 }
1328 
1329 /*!
1330     \internal
1331 
1332     This function has a confusing name and shouldn't be part of the
1333     API anyway, since we have toJulian() and fromJulian().
1334     ### Qt 5: remove it
1335 */
julianToGregorian(uint jd,int & y,int & m,int & d)1336 void QDate::julianToGregorian(uint jd, int &y, int &m, int &d)
1337 {
1338     getDateFromJulianDay(jd, &y, &m, &d);
1339 }
1340 
1341 /*! \fn static QDate QDate::fromJulianDay(int jd)
1342 
1343     Converts the Julian day \a jd to a QDate.
1344 
1345     \sa toJulianDay()
1346 */
1347 
1348 /*! \fn int QDate::toJulianDay() const
1349 
1350     Converts the date to a Julian day.
1351 
1352     \sa fromJulianDay()
1353 */
1354 
1355 /*****************************************************************************
1356   QTime member functions
1357  *****************************************************************************/
1358 
1359 /*!
1360     \class QTime
1361     \reentrant
1362 
1363     \brief The QTime class provides clock time functions.
1364 
1365 
1366     A QTime object contains a clock time, i.e. the number of hours,
1367     minutes, seconds, and milliseconds since midnight. It can read the
1368     current time from the system clock and measure a span of elapsed
1369     time. It provides functions for comparing times and for
1370     manipulating a time by adding a number of milliseconds.
1371 
1372     QTime uses the 24-hour clock format; it has no concept of AM/PM.
1373     Unlike QDateTime, QTime knows nothing about time zones or
1374     daylight savings time (DST).
1375 
1376     A QTime object is typically created either by giving the number
1377     of hours, minutes, seconds, and milliseconds explicitly, or by
1378     using the static function currentTime(), which creates a QTime
1379     object that contains the system's local time. Note that the
1380     accuracy depends on the accuracy of the underlying operating
1381     system; not all systems provide 1-millisecond accuracy.
1382 
1383     The hour(), minute(), second(), and msec() functions provide
1384     access to the number of hours, minutes, seconds, and milliseconds
1385     of the time. The same information is provided in textual format by
1386     the toString() function.
1387 
1388     QTime provides a full set of operators to compare two QTime
1389     objects. One time is considered smaller than another if it is
1390     earlier than the other.
1391 
1392     The time a given number of seconds or milliseconds later than a
1393     given time can be found using the addSecs() or addMSecs()
1394     functions. Correspondingly, the number of seconds or milliseconds
1395     between two times can be found using secsTo() or msecsTo().
1396 
1397     QTime can be used to measure a span of elapsed time using the
1398     start(), restart(), and elapsed() functions.
1399 
1400     \sa QDate, QDateTime
1401 */
1402 
1403 /*!
1404     \fn QTime::QTime()
1405 
1406     Constructs a null time object. A null time can be a QTime(0, 0, 0, 0)
1407     (i.e., midnight) object, except that isNull() returns true and isValid()
1408     returns false.
1409 
1410     \sa isNull(), isValid()
1411 */
1412 
1413 /*!
1414     Constructs a time with hour \a h, minute \a m, seconds \a s and
1415     milliseconds \a ms.
1416 
1417     \a h must be in the range 0 to 23, \a m and \a s must be in the
1418     range 0 to 59, and \a ms must be in the range 0 to 999.
1419 
1420     \sa isValid()
1421 */
1422 
QTime(int h,int m,int s,int ms)1423 QTime::QTime(int h, int m, int s, int ms)
1424 {
1425     setHMS(h, m, s, ms);
1426 }
1427 
1428 
1429 /*!
1430     \fn bool QTime::isNull() const
1431 
1432     Returns true if the time is null (i.e., the QTime object was
1433     constructed using the default constructor); otherwise returns
1434     false. A null time is also an invalid time.
1435 
1436     \sa isValid()
1437 */
1438 
1439 /*!
1440     Returns true if the time is valid; otherwise returns false. For example,
1441     the time 23:30:55.746 is valid, but 24:12:30 is invalid.
1442 
1443     \sa isNull()
1444 */
1445 
isValid() const1446 bool QTime::isValid() const
1447 {
1448     return mds > NullTime && mds < MSECS_PER_DAY;
1449 }
1450 
1451 
1452 /*!
1453     Returns the hour part (0 to 23) of the time.
1454 
1455     \sa minute(), second(), msec()
1456 */
1457 
hour() const1458 int QTime::hour() const
1459 {
1460     return ds() / MSECS_PER_HOUR;
1461 }
1462 
1463 /*!
1464     Returns the minute part (0 to 59) of the time.
1465 
1466     \sa hour(), second(), msec()
1467 */
1468 
minute() const1469 int QTime::minute() const
1470 {
1471     return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
1472 }
1473 
1474 /*!
1475     Returns the second part (0 to 59) of the time.
1476 
1477     \sa hour(), minute(), msec()
1478 */
1479 
second() const1480 int QTime::second() const
1481 {
1482     return (ds() / 1000)%SECS_PER_MIN;
1483 }
1484 
1485 /*!
1486     Returns the millisecond part (0 to 999) of the time.
1487 
1488     \sa hour(), minute(), second()
1489 */
1490 
msec() const1491 int QTime::msec() const
1492 {
1493     return ds() % 1000;
1494 }
1495 
1496 #ifndef QT_NO_DATESTRING
1497 /*!
1498     \overload
1499 
1500     Returns the time as a string. Milliseconds are not included. The
1501     \a format parameter determines the format of the string.
1502 
1503     If \a format is Qt::TextDate, the string format is HH:mm:ss; e.g. 1
1504     second before midnight would be "23:59:59".
1505 
1506     If \a format is Qt::ISODate, the string format corresponds to the
1507     ISO 8601 extended specification for representations of dates,
1508     which is also HH:mm:ss. (However, contrary to ISO 8601, dates
1509     before 15 October 1582 are handled as Julian dates, not Gregorian
1510     dates. See \l{QDate G and J} {Use of Gregorian and Julian
1511     Calendars}. This might change in a future version of Qt.)
1512 
1513     If the \a format is Qt::SystemLocaleShortDate or
1514     Qt::SystemLocaleLongDate, the string format depends on the locale
1515     settings of the system. Identical to calling
1516     QLocale::system().toString(time, QLocale::ShortFormat) or
1517     QLocale::system().toString(time, QLocale::LongFormat).
1518 
1519     If the \a format is Qt::DefaultLocaleShortDate or
1520     Qt::DefaultLocaleLongDate, the string format depends on the
1521     default application locale. This is the locale set with
1522     QLocale::setDefault(), or the system locale if no default locale
1523     has been set. Identical to calling QLocale().toString(time,
1524     QLocale::ShortFormat) or QLocale().toString(time,
1525     QLocale::LongFormat).
1526 
1527     If the time is invalid, an empty string will be returned.
1528 */
1529 
toString(Qt::DateFormat format) const1530 QString QTime::toString(Qt::DateFormat format) const
1531 {
1532     if (!isValid())
1533         return QString();
1534 
1535     switch (format) {
1536     case Qt::SystemLocaleDate:
1537     case Qt::SystemLocaleShortDate:
1538     case Qt::SystemLocaleLongDate:
1539         return QLocale::system().toString(*this, format == Qt::SystemLocaleLongDate ? QLocale::LongFormat
1540                                           : QLocale::ShortFormat);
1541     case Qt::LocaleDate:
1542     case Qt::DefaultLocaleShortDate:
1543     case Qt::DefaultLocaleLongDate:
1544         return QLocale().toString(*this, format == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
1545                                   : QLocale::ShortFormat);
1546 
1547     default:
1548     case Qt::ISODate:
1549     case Qt::TextDate:
1550         return QString::fromLatin1("%1:%2:%3")
1551             .arg(hour(), 2, 10, QLatin1Char('0'))
1552             .arg(minute(), 2, 10, QLatin1Char('0'))
1553             .arg(second(), 2, 10, QLatin1Char('0'));
1554     }
1555 }
1556 
1557 /*!
1558     Returns the time as a string. The \a format parameter determines
1559     the format of the result string.
1560 
1561     These expressions may be used:
1562 
1563     \table
1564     \header \i Expression \i Output
1565     \row \i h
1566          \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
1567     \row \i hh
1568          \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
1569     \row \i H
1570          \i the hour without a leading zero (0 to 23, even with AM/PM display)
1571     \row \i HH
1572          \i the hour with a leading zero (00 to 23, even with AM/PM display)
1573     \row \i m \i the minute without a leading zero (0 to 59)
1574     \row \i mm \i the minute with a leading zero (00 to 59)
1575     \row \i s \i the second without a leading zero (0 to 59)
1576     \row \i ss \i the second with a leading zero (00 to 59)
1577     \row \i z \i the milliseconds without leading zeroes (0 to 999)
1578     \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
1579     \row \i AP or A
1580          \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
1581     \row \i ap or a
1582          \i use am/pm display. \e ap will be replaced by either "am" or "pm".
1583     \row \i t \i the timezone (for example "CEST")
1584     \endtable
1585 
1586     All other input characters will be ignored. Any sequence of characters that
1587     are enclosed in singlequotes will be treated as text and not be used as an
1588     expression. Two consecutive singlequotes ("''") are replaced by a singlequote
1589     in the output.
1590 
1591     Example format strings (assuming that the QTime is 14:13:09.042)
1592 
1593     \table
1594     \header \i Format \i Result
1595     \row \i hh:mm:ss.zzz \i 14:13:09.042
1596     \row \i h:m:s ap     \i 2:13:9 pm
1597     \row \i H:m:s a      \i 14:13:9 pm
1598     \endtable
1599 
1600     If the datetime is invalid, an empty string will be returned.
1601     If \a format is empty, the default format "hh:mm:ss" is used.
1602 
1603     \sa QDate::toString() QDateTime::toString()
1604 */
toString(const QString & format) const1605 QString QTime::toString(const QString& format) const
1606 {
1607     return fmtDateTime(format, this, 0);
1608 }
1609 #endif //QT_NO_DATESTRING
1610 /*!
1611     Sets the time to hour \a h, minute \a m, seconds \a s and
1612     milliseconds \a ms.
1613 
1614     \a h must be in the range 0 to 23, \a m and \a s must be in the
1615     range 0 to 59, and \a ms must be in the range 0 to 999.
1616     Returns true if the set time is valid; otherwise returns false.
1617 
1618     \sa isValid()
1619 */
1620 
setHMS(int h,int m,int s,int ms)1621 bool QTime::setHMS(int h, int m, int s, int ms)
1622 {
1623 #if defined(Q_OS_WINCE)
1624     startTick = NullTime;
1625 #endif
1626     if (!isValid(h,m,s,ms)) {
1627         mds = NullTime;                // make this invalid
1628         return false;
1629     }
1630     mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
1631     return true;
1632 }
1633 
1634 /*!
1635     Returns a QTime object containing a time \a s seconds later
1636     than the time of this object (or earlier if \a s is negative).
1637 
1638     Note that the time will wrap if it passes midnight.
1639 
1640     Example:
1641 
1642     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 5
1643 
1644     \sa addMSecs(), secsTo(), QDateTime::addSecs()
1645 */
1646 
addSecs(int s) const1647 QTime QTime::addSecs(int s) const
1648 {
1649     return addMSecs(s * 1000);
1650 }
1651 
1652 /*!
1653     Returns the number of seconds from this time to \a t.
1654     If \a t is earlier than this time, the number of seconds returned
1655     is negative.
1656 
1657     Because QTime measures time within a day and there are 86400
1658     seconds in a day, the result is always between -86400 and 86400.
1659 
1660     secsTo() does not take into account any milliseconds.
1661 
1662     \sa addSecs(), QDateTime::secsTo()
1663 */
1664 
secsTo(const QTime & t) const1665 int QTime::secsTo(const QTime &t) const
1666 {
1667     return (t.ds() - ds()) / 1000;
1668 }
1669 
1670 /*!
1671     Returns a QTime object containing a time \a ms milliseconds later
1672     than the time of this object (or earlier if \a ms is negative).
1673 
1674     Note that the time will wrap if it passes midnight. See addSecs()
1675     for an example.
1676 
1677     \sa addSecs(), msecsTo(), QDateTime::addMSecs()
1678 */
1679 
addMSecs(int ms) const1680 QTime QTime::addMSecs(int ms) const
1681 {
1682     QTime t;
1683     if (ms < 0) {
1684         // % not well-defined for -ve, but / is.
1685         int negdays = (MSECS_PER_DAY - ms) / MSECS_PER_DAY;
1686         t.mds = (ds() + ms + negdays * MSECS_PER_DAY) % MSECS_PER_DAY;
1687     } else {
1688         t.mds = (ds() + ms) % MSECS_PER_DAY;
1689     }
1690 #if defined(Q_OS_WINCE)
1691     if (startTick > NullTime)
1692         t.startTick = (startTick + ms) % MSECS_PER_DAY;
1693 #endif
1694     return t;
1695 }
1696 
1697 /*!
1698     Returns the number of milliseconds from this time to \a t.
1699     If \a t is earlier than this time, the number of milliseconds returned
1700     is negative.
1701 
1702     Because QTime measures time within a day and there are 86400
1703     seconds in a day, the result is always between -86400000 and
1704     86400000 ms.
1705 
1706     \sa secsTo(), addMSecs(), QDateTime::msecsTo()
1707 */
1708 
msecsTo(const QTime & t) const1709 int QTime::msecsTo(const QTime &t) const
1710 {
1711 #if defined(Q_OS_WINCE)
1712     // GetLocalTime() for Windows CE has no milliseconds resolution
1713     if (t.startTick > NullTime && startTick > NullTime)
1714         return t.startTick - startTick;
1715     else
1716 #endif
1717         return t.ds() - ds();
1718 }
1719 
1720 
1721 /*!
1722     \fn bool QTime::operator==(const QTime &t) const
1723 
1724     Returns true if this time is equal to \a t; otherwise returns false.
1725 */
1726 
1727 /*!
1728     \fn bool QTime::operator!=(const QTime &t) const
1729 
1730     Returns true if this time is different from \a t; otherwise returns false.
1731 */
1732 
1733 /*!
1734     \fn bool QTime::operator<(const QTime &t) const
1735 
1736     Returns true if this time is earlier than \a t; otherwise returns false.
1737 */
1738 
1739 /*!
1740     \fn bool QTime::operator<=(const QTime &t) const
1741 
1742     Returns true if this time is earlier than or equal to \a t;
1743     otherwise returns false.
1744 */
1745 
1746 /*!
1747     \fn bool QTime::operator>(const QTime &t) const
1748 
1749     Returns true if this time is later than \a t; otherwise returns false.
1750 */
1751 
1752 /*!
1753     \fn bool QTime::operator>=(const QTime &t) const
1754 
1755     Returns true if this time is later than or equal to \a t;
1756     otherwise returns false.
1757 */
1758 
1759 /*!
1760     \fn QTime::currentTime()
1761 
1762     Returns the current time as reported by the system clock.
1763 
1764     Note that the accuracy depends on the accuracy of the underlying
1765     operating system; not all systems provide 1-millisecond accuracy.
1766 */
1767 
1768 #ifndef QT_NO_DATESTRING
1769 /*!
1770     \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format)
1771 
1772     Returns the time represented in the \a string as a QTime using the
1773     \a format given, or an invalid time if this is not possible.
1774 
1775     Note that fromString() uses a "C" locale encoded string to convert
1776     milliseconds to a float value. If the default locale is not "C",
1777     this may result in two conversion attempts (if the conversion
1778     fails for the default locale). This should be considered an
1779     implementation detail.
1780 */
fromString(const QString & s,Qt::DateFormat f)1781 QTime QTime::fromString(const QString& s, Qt::DateFormat f)
1782 {
1783     if (s.isEmpty()) {
1784         QTime t;
1785         t.mds = NullTime;
1786         return t;
1787     }
1788 
1789     switch (f) {
1790     case Qt::SystemLocaleDate:
1791     case Qt::SystemLocaleShortDate:
1792     case Qt::SystemLocaleLongDate:
1793         return fromString(s, QLocale::system().timeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
1794                                                                                         : QLocale::ShortFormat));
1795     case Qt::LocaleDate:
1796     case Qt::DefaultLocaleShortDate:
1797     case Qt::DefaultLocaleLongDate:
1798         return fromString(s, QLocale().timeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
1799                                                                                  : QLocale::ShortFormat));
1800     default:
1801         {
1802             bool ok = true;
1803             const int hour(s.mid(0, 2).toInt(&ok));
1804             if (!ok)
1805                 return QTime();
1806             const int minute(s.mid(3, 2).toInt(&ok));
1807             if (!ok)
1808                 return QTime();
1809             const int second(s.mid(6, 2).toInt(&ok));
1810             if (!ok)
1811                 return QTime();
1812             const QString msec_s(QLatin1String("0.") + s.mid(9, 4));
1813             const float msec(msec_s.toFloat(&ok));
1814             if (!ok)
1815                 return QTime(hour, minute, second, 0);
1816             return QTime(hour, minute, second, qMin(qRound(msec * 1000.0), 999));
1817         }
1818     }
1819 }
1820 
1821 /*!
1822     \fn QTime::fromString(const QString &string, const QString &format)
1823 
1824     Returns the QTime represented by the \a string, using the \a
1825     format given, or an invalid time if the string cannot be parsed.
1826 
1827     These expressions may be used for the format:
1828 
1829     \table
1830     \header \i Expression \i Output
1831     \row \i h
1832          \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
1833     \row \i hh
1834          \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
1835     \row \i m \i the minute without a leading zero (0 to 59)
1836     \row \i mm \i the minute with a leading zero (00 to 59)
1837     \row \i s \i the second without a leading zero (0 to 59)
1838     \row \i ss \i the second with a leading zero (00 to 59)
1839     \row \i z \i the milliseconds without leading zeroes (0 to 999)
1840     \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
1841     \row \i AP
1842          \i interpret as an AM/PM time. \e AP must be either "AM" or "PM".
1843     \row \i ap
1844          \i Interpret as an AM/PM time. \e ap must be either "am" or "pm".
1845     \endtable
1846 
1847     All other input characters will be treated as text. Any sequence
1848     of characters that are enclosed in single quotes will also be
1849     treated as text and not be used as an expression.
1850 
1851     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 6
1852 
1853     If the format is not satisfied an invalid QTime is returned.
1854     Expressions that do not expect leading zeroes to be given (h, m, s
1855     and z) are greedy. This means that they will use two digits even if
1856     this puts them outside the range of accepted values and leaves too
1857     few digits for other sections. For example, the following string
1858     could have meant 00:07:10, but the m will grab two digits, resulting
1859     in an invalid time:
1860 
1861     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 7
1862 
1863     Any field that is not represented in the format will be set to zero.
1864     For example:
1865 
1866     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 8
1867 
1868     \sa QDateTime::fromString() QDate::fromString() QDate::toString()
1869     QDateTime::toString() QTime::toString()
1870 */
1871 
fromString(const QString & string,const QString & format)1872 QTime QTime::fromString(const QString &string, const QString &format)
1873 {
1874     QTime time;
1875 #ifndef QT_BOOTSTRAPPED
1876     QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
1877     if (dt.parseFormat(format))
1878         dt.fromString(string, 0, &time);
1879 #else
1880     Q_UNUSED(string);
1881     Q_UNUSED(format);
1882 #endif
1883     return time;
1884 }
1885 
1886 #endif // QT_NO_DATESTRING
1887 
1888 
1889 /*!
1890     \overload
1891 
1892     Returns true if the specified time is valid; otherwise returns
1893     false.
1894 
1895     The time is valid if \a h is in the range 0 to 23, \a m and
1896     \a s are in the range 0 to 59, and \a ms is in the range 0 to 999.
1897 
1898     Example:
1899 
1900     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 9
1901 */
1902 
isValid(int h,int m,int s,int ms)1903 bool QTime::isValid(int h, int m, int s, int ms)
1904 {
1905     return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
1906 }
1907 
1908 
1909 /*!
1910     Sets this time to the current time. This is practical for timing:
1911 
1912     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 10
1913 
1914     \sa restart(), elapsed(), currentTime()
1915 */
1916 
start()1917 void QTime::start()
1918 {
1919     *this = currentTime();
1920 }
1921 
1922 /*!
1923     Sets this time to the current time and returns the number of
1924     milliseconds that have elapsed since the last time start() or
1925     restart() was called.
1926 
1927     This function is guaranteed to be atomic and is thus very handy
1928     for repeated measurements. Call start() to start the first
1929     measurement, and restart() for each later measurement.
1930 
1931     Note that the counter wraps to zero 24 hours after the last call
1932     to start() or restart().
1933 
1934     \warning If the system's clock setting has been changed since the
1935     last time start() or restart() was called, the result is
1936     undefined. This can happen when daylight savings time is turned on
1937     or off.
1938 
1939     \sa start(), elapsed(), currentTime()
1940 */
1941 
restart()1942 int QTime::restart()
1943 {
1944     QTime t = currentTime();
1945     int n = msecsTo(t);
1946     if (n < 0)                                // passed midnight
1947         n += 86400*1000;
1948     *this = t;
1949     return n;
1950 }
1951 
1952 /*!
1953     Returns the number of milliseconds that have elapsed since the
1954     last time start() or restart() was called.
1955 
1956     Note that the counter wraps to zero 24 hours after the last call
1957     to start() or restart.
1958 
1959     Note that the accuracy depends on the accuracy of the underlying
1960     operating system; not all systems provide 1-millisecond accuracy.
1961 
1962     \warning If the system's clock setting has been changed since the
1963     last time start() or restart() was called, the result is
1964     undefined. This can happen when daylight savings time is turned on
1965     or off.
1966 
1967     \sa start(), restart()
1968 */
1969 
elapsed() const1970 int QTime::elapsed() const
1971 {
1972     int n = msecsTo(currentTime());
1973     if (n < 0)                                // passed midnight
1974         n += 86400 * 1000;
1975     return n;
1976 }
1977 
1978 
1979 /*****************************************************************************
1980   QDateTime member functions
1981  *****************************************************************************/
1982 
1983 /*!
1984     \class QDateTime
1985     \reentrant
1986     \brief The QDateTime class provides date and time functions.
1987 
1988 
1989     A QDateTime object contains a calendar date and a clock time (a
1990     "datetime"). It is a combination of the QDate and QTime classes.
1991     It can read the current datetime from the system clock. It
1992     provides functions for comparing datetimes and for manipulating a
1993     datetime by adding a number of seconds, days, months, or years.
1994 
1995     A QDateTime object is typically created either by giving a date
1996     and time explicitly in the constructor, or by using the static
1997     function currentDateTime() that returns a QDateTime object set
1998     to the system clock's time. The date and time can be changed with
1999     setDate() and setTime(). A datetime can also be set using the
2000     setTime_t() function that takes a POSIX-standard "number of
2001     seconds since 00:00:00 on January 1, 1970" value. The fromString()
2002     function returns a QDateTime, given a string and a date format
2003     used to interpret the date within the string.
2004 
2005     The date() and time() functions provide access to the date and
2006     time parts of the datetime. The same information is provided in
2007     textual format by the toString() function.
2008 
2009     QDateTime provides a full set of operators to compare two
2010     QDateTime objects where smaller means earlier and larger means
2011     later.
2012 
2013     You can increment (or decrement) a datetime by a given number of
2014     milliseconds using addMSecs(), seconds using addSecs(), or days
2015     using addDays(). Similarly you can use addMonths() and addYears().
2016     The daysTo() function returns the number of days between two datetimes,
2017     secsTo() returns the number of seconds between two datetimes, and
2018     msecsTo() returns the number of milliseconds between two datetimes.
2019 
2020     QDateTime can store datetimes as \l{Qt::LocalTime}{local time} or
2021     as \l{Qt::UTC}{UTC}. QDateTime::currentDateTime() returns a
2022     QDateTime expressed as local time; use toUTC() to convert it to
2023     UTC. You can also use timeSpec() to find out if a QDateTime
2024     object stores a UTC time or a local time. Operations such as
2025     addSecs() and secsTo() are aware of daylight saving time (DST).
2026 
2027     \note QDateTime does not account for leap seconds.
2028 
2029     \section1
2030 
2031     \target QDateTime G and J
2032     \section2 Use of Gregorian and Julian Calendars
2033 
2034     QDate uses the Gregorian calendar in all locales, beginning
2035     on the date 15 October 1582. For dates up to and including 4
2036     October 1582, the Julian calendar is used.  This means there is a
2037     10-day gap in the internal calendar between the 4th and the 15th
2038     of October 1582. When you use QDateTime for dates in that epoch,
2039     the day after 4 October 1582 is 15 October 1582, and the dates in
2040     the gap are invalid.
2041 
2042     The Julian to Gregorian changeover date used here is the date when
2043     the Gregorian calendar was first introduced, by Pope Gregory
2044     XIII. That change was not universally accepted and some localities
2045     only executed it at a later date (if at all).  QDateTime
2046     doesn't take any of these historical facts into account. If an
2047     application must support a locale-specific dating system, it must
2048     do so on its own, remembering to convert the dates using the
2049     Julian day.
2050 
2051     \section2 No Year 0
2052 
2053     There is no year 0. Dates in that year are considered invalid. The
2054     year -1 is the year "1 before Christ" or "1 before current era."
2055     The day before 0001-01-01 is December 31st, 1 BCE.
2056 
2057     \section2 Range of Valid Dates
2058 
2059     The range of valid dates is from January 2nd, 4713 BCE, to
2060     sometime in the year 11 million CE. The Julian Day returned by
2061     QDate::toJulianDay() is a number in the contiguous range from 1 to
2062     \e{overflow}, even across QDateTime's "date holes". It is suitable
2063     for use in applications that must convert a QDateTime to a date in
2064     another calendar system, e.g., Hebrew, Islamic or Chinese.
2065 
2066     The Gregorian calendar was introduced in different places around
2067     the world on different dates. QDateTime uses QDate to store the
2068     date, so it uses the Gregorian calendar for all locales, beginning
2069     on the date 15 October 1582. For dates up to and including 4
2070     October 1582, QDateTime uses the Julian calendar.  This means
2071     there is a 10-day gap in the QDateTime calendar between the 4th
2072     and the 15th of October 1582. When you use QDateTime for dates in
2073     that epoch, the day after 4 October 1582 is 15 October 1582, and
2074     the dates in the gap are invalid.
2075 
2076     \section2
2077     Use of System Timezone
2078 
2079     QDateTime uses the system's time zone information to determine the
2080     offset of local time from UTC. If the system is not configured
2081     correctly or not up-to-date, QDateTime will give wrong results as
2082     well.
2083 
2084     \section2 Daylight Savings Time (DST)
2085 
2086     QDateTime takes into account the system's time zone information
2087     when dealing with DST. On modern Unix systems, this means it
2088     applies the correct historical DST data whenever possible. On
2089     Windows and Windows CE, where the system doesn't support
2090     historical DST data, historical accuracy is not maintained with
2091     respect to DST.
2092 
2093     The range of valid dates taking DST into account is 1970-01-01 to
2094     the present, and rules are in place for handling DST correctly
2095     until 2037-12-31, but these could change. For dates falling
2096     outside that range, QDateTime makes a \e{best guess} using the
2097     rules for year 1970 or 2037, but we can't guarantee accuracy. This
2098     means QDateTime doesn't take into account changes in a locale's
2099     time zone before 1970, even if the system's time zone database
2100     supports that information.
2101 
2102     \sa QDate QTime QDateTimeEdit
2103 */
2104 
2105 /*!
2106     Constructs a null datetime (i.e. null date and null time). A null
2107     datetime is invalid, since the date is invalid.
2108 
2109     \sa isValid()
2110 */
QDateTime()2111 QDateTime::QDateTime()
2112     : d(new QDateTimePrivate)
2113 {
2114 }
2115 
2116 
2117 /*!
2118     Constructs a datetime with the given \a date, a valid
2119     time(00:00:00.000), and sets the timeSpec() to Qt::LocalTime.
2120 */
2121 
QDateTime(const QDate & date)2122 QDateTime::QDateTime(const QDate &date)
2123     : d(new QDateTimePrivate)
2124 {
2125     d->date = date;
2126     d->time = QTime(0, 0, 0);
2127 }
2128 
2129 /*!
2130     Constructs a datetime with the given \a date and \a time, using
2131     the time specification defined by \a spec.
2132 
2133     If \a date is valid and \a time is not, the time will be set to midnight.
2134 */
2135 
QDateTime(const QDate & date,const QTime & time,Qt::TimeSpec spec)2136 QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
2137     : d(new QDateTimePrivate)
2138 {
2139     d->date = date;
2140     d->time = date.isValid() && !time.isValid() ? QTime(0, 0, 0) : time;
2141     d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown;
2142 }
2143 
2144 /*!
2145     Constructs a copy of the \a other datetime.
2146 */
2147 
QDateTime(const QDateTime & other)2148 QDateTime::QDateTime(const QDateTime &other)
2149     : d(other.d)
2150 {
2151 }
2152 
2153 /*!
2154     Destroys the datetime.
2155 */
~QDateTime()2156 QDateTime::~QDateTime()
2157 {
2158 }
2159 
2160 /*!
2161     Makes a copy of the \a other datetime and returns a reference to the
2162     copy.
2163 */
2164 
operator =(const QDateTime & other)2165 QDateTime &QDateTime::operator=(const QDateTime &other)
2166 {
2167     d = other.d;
2168     return *this;
2169 }
2170 
2171 /*!
2172     Returns true if both the date and the time are null; otherwise
2173     returns false. A null datetime is invalid.
2174 
2175     \sa QDate::isNull(), QTime::isNull(), isValid()
2176 */
2177 
isNull() const2178 bool QDateTime::isNull() const
2179 {
2180     return d->date.isNull() && d->time.isNull();
2181 }
2182 
2183 /*!
2184     Returns true if both the date and the time are valid; otherwise
2185     returns false.
2186 
2187     \sa QDate::isValid(), QTime::isValid()
2188 */
2189 
isValid() const2190 bool QDateTime::isValid() const
2191 {
2192     return d->date.isValid() && d->time.isValid();
2193 }
2194 
2195 /*!
2196     Returns the date part of the datetime.
2197 
2198     \sa setDate(), time(), timeSpec()
2199 */
2200 
date() const2201 QDate QDateTime::date() const
2202 {
2203     return d->date;
2204 }
2205 
2206 /*!
2207     Returns the time part of the datetime.
2208 
2209     \sa setTime(), date(), timeSpec()
2210 */
2211 
time() const2212 QTime QDateTime::time() const
2213 {
2214     return d->time;
2215 }
2216 
2217 /*!
2218     Returns the time specification of the datetime.
2219 
2220     \sa setTimeSpec(), date(), time(), Qt::TimeSpec
2221 */
2222 
timeSpec() const2223 Qt::TimeSpec QDateTime::timeSpec() const
2224 {
2225     switch(d->spec)
2226     {
2227         case QDateTimePrivate::UTC:
2228             return Qt::UTC;
2229         case QDateTimePrivate::OffsetFromUTC:
2230             return Qt::OffsetFromUTC;
2231         default:
2232             return Qt::LocalTime;
2233     }
2234 }
2235 
2236 /*!
2237     Sets the date part of this datetime to \a date.
2238     If no time is set, it is set to midnight.
2239 
2240     \sa date(), setTime(), setTimeSpec()
2241 */
2242 
setDate(const QDate & date)2243 void QDateTime::setDate(const QDate &date)
2244 {
2245     detach();
2246     d->date = date;
2247     if (d->spec == QDateTimePrivate::LocalStandard
2248         || d->spec == QDateTimePrivate::LocalDST)
2249         d->spec = QDateTimePrivate::LocalUnknown;
2250     if (date.isValid() && !d->time.isValid())
2251         d->time = QTime(0, 0, 0);
2252 }
2253 
2254 /*!
2255     Sets the time part of this datetime to \a time.
2256 
2257     \sa time(), setDate(), setTimeSpec()
2258 */
2259 
setTime(const QTime & time)2260 void QDateTime::setTime(const QTime &time)
2261 {
2262     detach();
2263     if (d->spec == QDateTimePrivate::LocalStandard
2264         || d->spec == QDateTimePrivate::LocalDST)
2265         d->spec = QDateTimePrivate::LocalUnknown;
2266     d->time = time;
2267 }
2268 
2269 /*!
2270     Sets the time specification used in this datetime to \a spec.
2271 
2272     \sa timeSpec(), setDate(), setTime(), Qt::TimeSpec
2273 */
2274 
setTimeSpec(Qt::TimeSpec spec)2275 void QDateTime::setTimeSpec(Qt::TimeSpec spec)
2276 {
2277     detach();
2278 
2279     switch(spec)
2280     {
2281         case Qt::UTC:
2282             d->spec = QDateTimePrivate::UTC;
2283             break;
2284         case Qt::OffsetFromUTC:
2285             d->spec = QDateTimePrivate::OffsetFromUTC;
2286             break;
2287         default:
2288             d->spec = QDateTimePrivate::LocalUnknown;
2289             break;
2290     }
2291 }
2292 
toMSecsSinceEpoch_helper(qint64 jd,int msecs)2293 qint64 toMSecsSinceEpoch_helper(qint64 jd, int msecs)
2294 {
2295     qint64 days = jd - JULIAN_DAY_FOR_EPOCH;
2296     qint64 retval = (days * MSECS_PER_DAY) + msecs;
2297     return retval;
2298 }
2299 
2300 /*!
2301     \since 4.7
2302 
2303     Returns the datetime as the number of milliseconds that have passed
2304     since 1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
2305 
2306     On systems that do not support time zones, this function will
2307     behave as if local time were Qt::UTC.
2308 
2309     The behavior for this function is undefined if the datetime stored in
2310     this object is not valid. However, for all valid dates, this function
2311     returns a unique value.
2312 
2313     \sa toTime_t(), setMSecsSinceEpoch()
2314 */
toMSecsSinceEpoch() const2315 qint64 QDateTime::toMSecsSinceEpoch() const
2316 {
2317     QDate utcDate;
2318     QTime utcTime;
2319     d->getUTC(utcDate, utcTime);
2320 
2321     return toMSecsSinceEpoch_helper(utcDate.jd, utcTime.ds());
2322 }
2323 
2324 /*!
2325     Returns the datetime as the number of seconds that have passed
2326     since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
2327 
2328     On systems that do not support time zones, this function will
2329     behave as if local time were Qt::UTC.
2330 
2331     \note This function returns a 32-bit unsigned integer, so it does not
2332     support dates before 1970, but it does support dates after
2333     2038-01-19T03:14:06, which may not be valid time_t values. Be careful
2334     when passing those time_t values to system functions, which could
2335     interpret them as negative dates.
2336 
2337     If the date is outside the range 1970-01-01T00:00:00 to
2338     2106-02-07T06:28:14, this function returns -1 cast to an unsigned integer
2339     (i.e., 0xFFFFFFFF).
2340 
2341     To get an extended range, use toMSecsSinceEpoch().
2342 
2343     \sa toMSecsSinceEpoch(), setTime_t()
2344 */
2345 
toTime_t() const2346 uint QDateTime::toTime_t() const
2347 {
2348     qint64 retval = toMSecsSinceEpoch() / 1000;
2349     if (quint64(retval) >= Q_UINT64_C(0xFFFFFFFF))
2350         return uint(-1);
2351     return uint(retval);
2352 }
2353 
2354 /*!
2355     \since 4.7
2356 
2357     Sets the date and time given the number of milliseconds,\a msecs, that have
2358     passed since 1970-01-01T00:00:00.000, Coordinated Universal Time
2359     (Qt::UTC). On systems that do not support time zones this function
2360     will behave as if local time were Qt::UTC.
2361 
2362     Note that there are possible values for \a msecs that lie outside the
2363     valid range of QDateTime, both negative and positive. The behavior of
2364     this function is undefined for those values.
2365 
2366     \sa toMSecsSinceEpoch(), setTime_t()
2367 */
setMSecsSinceEpoch(qint64 msecs)2368 void QDateTime::setMSecsSinceEpoch(qint64 msecs)
2369 {
2370     detach();
2371 
2372     QDateTimePrivate::Spec oldSpec = d->spec;
2373 
2374     int ddays = msecs / MSECS_PER_DAY;
2375     msecs %= MSECS_PER_DAY;
2376     if (msecs < 0) {
2377         // negative
2378         --ddays;
2379         msecs += MSECS_PER_DAY;
2380     }
2381 
2382     d->date = QDate(1970, 1, 1).addDays(ddays);
2383     d->time = QTime().addMSecs(msecs);
2384     d->spec = QDateTimePrivate::UTC;
2385 
2386     if (oldSpec != QDateTimePrivate::UTC)
2387         d->spec = d->getLocal(d->date, d->time);
2388 }
2389 
2390 /*!
2391     \fn void QDateTime::setTime_t(uint seconds)
2392 
2393     Sets the date and time given the number of \a seconds that have
2394     passed since 1970-01-01T00:00:00, Coordinated Universal Time
2395     (Qt::UTC). On systems that do not support time zones this function
2396     will behave as if local time were Qt::UTC.
2397 
2398     \sa toTime_t()
2399 */
2400 
setTime_t(uint secsSince1Jan1970UTC)2401 void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
2402 {
2403     detach();
2404 
2405     QDateTimePrivate::Spec oldSpec = d->spec;
2406 
2407     d->date = QDate(1970, 1, 1).addDays(secsSince1Jan1970UTC / SECS_PER_DAY);
2408     d->time = QTime().addSecs(secsSince1Jan1970UTC % SECS_PER_DAY);
2409     d->spec = QDateTimePrivate::UTC;
2410 
2411     if (oldSpec != QDateTimePrivate::UTC)
2412         d->spec = d->getLocal(d->date, d->time);
2413 }
2414 
2415 #ifndef QT_NO_DATESTRING
2416 /*!
2417     \fn QString QDateTime::toString(Qt::DateFormat format) const
2418 
2419     \overload
2420 
2421     Returns the datetime as a string in the \a format given.
2422 
2423     If the \a format is Qt::TextDate, the string is formatted in
2424     the default way. QDate::shortDayName(), QDate::shortMonthName(),
2425     and QTime::toString() are used to generate the string, so the
2426     day and month names will be localized names. An example of this
2427     formatting is "Wed May 20 03:40:13 1998".
2428 
2429     If the \a format is Qt::ISODate, the string format corresponds
2430     to the ISO 8601 extended specification for representations of
2431     dates and times, taking the form YYYY-MM-DDTHH:mm:ss[Z|[+|-]HH:mm],
2432     depending on the timeSpec() of the QDateTime. If the timeSpec()
2433     is Qt::UTC, Z will be appended to the string; if the timeSpec() is
2434     Qt::OffsetFromUTC the offset in hours and minutes from UTC will
2435     be appended to the string.
2436 
2437     If the \a format is Qt::SystemLocaleShortDate or
2438     Qt::SystemLocaleLongDate, the string format depends on the locale
2439     settings of the system. Identical to calling
2440     QLocale::system().toString(datetime, QLocale::ShortFormat) or
2441     QLocale::system().toString(datetime, QLocale::LongFormat).
2442 
2443     If the \a format is Qt::DefaultLocaleShortDate or
2444     Qt::DefaultLocaleLongDate, the string format depends on the
2445     default application locale. This is the locale set with
2446     QLocale::setDefault(), or the system locale if no default locale
2447     has been set. Identical to calling QLocale().toString(datetime,
2448     QLocale::ShortFormat) or QLocale().toString(datetime,
2449     QLocale::LongFormat).
2450 
2451     If the datetime is invalid, an empty string will be returned.
2452 
2453     \warning The Qt::ISODate format is only valid for years in the
2454     range 0 to 9999. This restriction may apply to locale-aware
2455     formats as well, depending on the locale settings.
2456 
2457     \sa QDate::toString() QTime::toString() Qt::DateFormat
2458 */
2459 
toString(Qt::DateFormat f) const2460 QString QDateTime::toString(Qt::DateFormat f) const
2461 {
2462     QString buf;
2463     if (!isValid())
2464         return buf;
2465 
2466     if (f == Qt::ISODate) {
2467         buf = d->date.toString(Qt::ISODate);
2468         if (buf.isEmpty())
2469             return QString();   // failed to convert
2470         buf += QLatin1Char('T');
2471         buf += d->time.toString(Qt::ISODate);
2472         switch (d->spec) {
2473         case QDateTimePrivate::UTC:
2474             buf += QLatin1Char('Z');
2475             break;
2476         case QDateTimePrivate::OffsetFromUTC: {
2477             int sign = d->utcOffset >= 0 ? 1: -1;
2478             buf += QString::fromLatin1("%1%2:%3").
2479                 arg(sign == 1 ? QLatin1Char('+') : QLatin1Char('-')).
2480                 arg(d->utcOffset * sign / SECS_PER_HOUR, 2, 10, QLatin1Char('0')).
2481                 arg((d->utcOffset / 60) % 60, 2, 10, QLatin1Char('0'));
2482             break;
2483         }
2484         default:
2485             break;
2486         }
2487     }
2488 #ifndef QT_NO_TEXTDATE
2489     else if (f == Qt::TextDate) {
2490 #ifndef Q_WS_WIN
2491         buf = d->date.shortDayName(d->date.dayOfWeek());
2492         buf += QLatin1Char(' ');
2493         buf += d->date.shortMonthName(d->date.month());
2494         buf += QLatin1Char(' ');
2495         buf += QString::number(d->date.day());
2496 #else
2497         wchar_t out[255];
2498         GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255);
2499         QString winstr = QString::fromWCharArray(out);
2500         switch (winstr.toInt()) {
2501         case 1:
2502             buf = d->date.shortDayName(d->date.dayOfWeek());
2503             buf += QLatin1Char(' ');
2504             buf += QString::number(d->date.day());
2505             buf += QLatin1String(". ");
2506             buf += d->date.shortMonthName(d->date.month());
2507             break;
2508         default:
2509             buf = d->date.shortDayName(d->date.dayOfWeek());
2510             buf += QLatin1Char(' ');
2511             buf += d->date.shortMonthName(d->date.month());
2512             buf += QLatin1Char(' ');
2513             buf += QString::number(d->date.day());
2514         }
2515 #endif
2516         buf += QLatin1Char(' ');
2517         buf += d->time.toString();
2518         buf += QLatin1Char(' ');
2519         buf += QString::number(d->date.year());
2520     }
2521 #endif
2522     else {
2523         buf = d->date.toString(f);
2524         if (buf.isEmpty())
2525             return QString();   // failed to convert
2526         buf += QLatin1Char(' ');
2527         buf += d->time.toString(f);
2528     }
2529 
2530     return buf;
2531 }
2532 
2533 /*!
2534     Returns the datetime as a string. The \a format parameter
2535     determines the format of the result string.
2536 
2537     These expressions may be used for the date:
2538 
2539     \table
2540     \header \i Expression \i Output
2541     \row \i d \i the day as number without a leading zero (1 to 31)
2542     \row \i dd \i the day as number with a leading zero (01 to 31)
2543     \row \i ddd
2544             \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
2545             Uses QDate::shortDayName().
2546     \row \i dddd
2547             \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
2548             Uses QDate::longDayName().
2549     \row \i M \i the month as number without a leading zero (1-12)
2550     \row \i MM \i the month as number with a leading zero (01-12)
2551     \row \i MMM
2552             \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
2553             Uses QDate::shortMonthName().
2554     \row \i MMMM
2555             \i the long localized month name (e.g. 'January' to 'December').
2556             Uses QDate::longMonthName().
2557     \row \i yy \i the year as two digit number (00-99)
2558     \row \i yyyy \i the year as four digit number
2559     \endtable
2560 
2561     These expressions may be used for the time:
2562 
2563     \table
2564     \header \i Expression \i Output
2565     \row \i h
2566          \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
2567     \row \i hh
2568          \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
2569     \row \i m \i the minute without a leading zero (0 to 59)
2570     \row \i mm \i the minute with a leading zero (00 to 59)
2571     \row \i s \i the second without a leading zero (0 to 59)
2572     \row \i ss \i the second with a leading zero (00 to 59)
2573     \row \i z \i the milliseconds without leading zeroes (0 to 999)
2574     \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
2575     \row \i AP
2576             \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
2577     \row \i ap
2578             \i use am/pm display. \e ap will be replaced by either "am" or "pm".
2579     \endtable
2580 
2581     All other input characters will be ignored. Any sequence of characters that
2582     are enclosed in singlequotes will be treated as text and not be used as an
2583     expression. Two consecutive singlequotes ("''") are replaced by a singlequote
2584     in the output.
2585 
2586     Example format strings (assumed that the QDateTime is 21 May 2001
2587     14:13:09):
2588 
2589     \table
2590     \header \i Format       \i Result
2591     \row \i dd.MM.yyyy      \i 21.05.2001
2592     \row \i ddd MMMM d yy   \i Tue May 21 01
2593     \row \i hh:mm:ss.zzz    \i 14:13:09.042
2594     \row \i h:m:s ap        \i 2:13:9 pm
2595     \endtable
2596 
2597     If the datetime is invalid, an empty string will be returned.
2598 
2599     \sa QDate::toString() QTime::toString()
2600 */
toString(const QString & format) const2601 QString QDateTime::toString(const QString& format) const
2602 {
2603     return fmtDateTime(format, &d->time, &d->date);
2604 }
2605 #endif //QT_NO_DATESTRING
2606 
2607 /*!
2608     Returns a QDateTime object containing a datetime \a ndays days
2609     later than the datetime of this object (or earlier if \a ndays is
2610     negative).
2611 
2612     \sa daysTo(), addMonths(), addYears(), addSecs()
2613 */
2614 
addDays(int ndays) const2615 QDateTime QDateTime::addDays(int ndays) const
2616 {
2617     return QDateTime(d->date.addDays(ndays), d->time, timeSpec());
2618 }
2619 
2620 /*!
2621     Returns a QDateTime object containing a datetime \a nmonths months
2622     later than the datetime of this object (or earlier if \a nmonths
2623     is negative).
2624 
2625     \sa daysTo(), addDays(), addYears(), addSecs()
2626 */
2627 
addMonths(int nmonths) const2628 QDateTime QDateTime::addMonths(int nmonths) const
2629 {
2630     return QDateTime(d->date.addMonths(nmonths), d->time, timeSpec());
2631 }
2632 
2633 /*!
2634     Returns a QDateTime object containing a datetime \a nyears years
2635     later than the datetime of this object (or earlier if \a nyears is
2636     negative).
2637 
2638     \sa daysTo(), addDays(), addMonths(), addSecs()
2639 */
2640 
addYears(int nyears) const2641 QDateTime QDateTime::addYears(int nyears) const
2642 {
2643     return QDateTime(d->date.addYears(nyears), d->time, timeSpec());
2644 }
2645 
addMSecs(const QDateTime & dt,qint64 msecs)2646 QDateTime QDateTimePrivate::addMSecs(const QDateTime &dt, qint64 msecs)
2647 {
2648     QDate utcDate;
2649     QTime utcTime;
2650     dt.d->getUTC(utcDate, utcTime);
2651 
2652     addMSecs(utcDate, utcTime, msecs);
2653 
2654     return QDateTime(utcDate, utcTime, Qt::UTC).toTimeSpec(dt.timeSpec());
2655 }
2656 
2657 /*!
2658  Adds \a msecs to utcDate and \a utcTime as appropriate. It is assumed that
2659  utcDate and utcTime are adjusted to UTC.
2660 
2661  \since 4.5
2662  \internal
2663  */
addMSecs(QDate & utcDate,QTime & utcTime,qint64 msecs)2664 void QDateTimePrivate::addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs)
2665 {
2666     uint dd = utcDate.jd;
2667     int tt = utcTime.ds();
2668     int sign = 1;
2669     if (msecs < 0) {
2670         msecs = -msecs;
2671         sign = -1;
2672     }
2673     if (msecs >= int(MSECS_PER_DAY)) {
2674         dd += sign * (msecs / MSECS_PER_DAY);
2675         msecs %= MSECS_PER_DAY;
2676     }
2677 
2678     tt += sign * msecs;
2679     if (tt < 0) {
2680         tt = MSECS_PER_DAY - tt - 1;
2681         dd -= tt / MSECS_PER_DAY;
2682         tt = tt % MSECS_PER_DAY;
2683         tt = MSECS_PER_DAY - tt - 1;
2684     } else if (tt >= int(MSECS_PER_DAY)) {
2685         dd += tt / MSECS_PER_DAY;
2686         tt = tt % MSECS_PER_DAY;
2687     }
2688 
2689     utcDate.jd = dd;
2690     utcTime.mds = tt;
2691 }
2692 
2693 /*!
2694     Returns a QDateTime object containing a datetime \a s seconds
2695     later than the datetime of this object (or earlier if \a s is
2696     negative).
2697 
2698     \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears()
2699 */
2700 
addSecs(int s) const2701 QDateTime QDateTime::addSecs(int s) const
2702 {
2703     return d->addMSecs(*this, qint64(s) * 1000);
2704 }
2705 
2706 /*!
2707     Returns a QDateTime object containing a datetime \a msecs miliseconds
2708     later than the datetime of this object (or earlier if \a msecs is
2709     negative).
2710 
2711     \sa addSecs(), msecsTo(), addDays(), addMonths(), addYears()
2712 */
addMSecs(qint64 msecs) const2713 QDateTime QDateTime::addMSecs(qint64 msecs) const
2714 {
2715     return d->addMSecs(*this, msecs);
2716 }
2717 
2718 /*!
2719     Returns the number of days from this datetime to the \a other
2720     datetime. If the \a other datetime is earlier than this datetime,
2721     the value returned is negative.
2722 
2723     \sa addDays(), secsTo(), msecsTo()
2724 */
2725 
daysTo(const QDateTime & other) const2726 int QDateTime::daysTo(const QDateTime &other) const
2727 {
2728     return d->date.daysTo(other.d->date);
2729 }
2730 
2731 /*!
2732     Returns the number of seconds from this datetime to the \a other
2733     datetime. If the \a other datetime is earlier than this datetime,
2734     the value returned is negative.
2735 
2736     Before performing the comparison, the two datetimes are converted
2737     to Qt::UTC to ensure that the result is correct if one of the two
2738     datetimes has daylight saving time (DST) and the other doesn't.
2739 
2740     Example:
2741     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 11
2742 
2743     \sa addSecs(), daysTo(), QTime::secsTo()
2744 */
2745 
secsTo(const QDateTime & other) const2746 int QDateTime::secsTo(const QDateTime &other) const
2747 {
2748     QDate date1, date2;
2749     QTime time1, time2;
2750 
2751     d->getUTC(date1, time1);
2752     other.d->getUTC(date2, time2);
2753 
2754     return (date1.daysTo(date2) * SECS_PER_DAY) + time1.secsTo(time2);
2755 }
2756 
2757 /*!
2758     \since 4.7
2759 
2760     Returns the number of milliseconds from this datetime to the \a other
2761     datetime. If the \a other datetime is earlier than this datetime,
2762     the value returned is negative.
2763 
2764     Before performing the comparison, the two datetimes are converted
2765     to Qt::UTC to ensure that the result is correct if one of the two
2766     datetimes has daylight saving time (DST) and the other doesn't.
2767 
2768     \sa addMSecs(), daysTo(), QTime::msecsTo()
2769 */
2770 
msecsTo(const QDateTime & other) const2771 qint64 QDateTime::msecsTo(const QDateTime &other) const
2772 {
2773     QDate selfDate;
2774     QDate otherDate;
2775     QTime selfTime;
2776     QTime otherTime;
2777 
2778     d->getUTC(selfDate, selfTime);
2779     other.d->getUTC(otherDate, otherTime);
2780 
2781     return (static_cast<qint64>(selfDate.daysTo(otherDate)) * static_cast<qint64>(MSECS_PER_DAY))
2782            + static_cast<qint64>(selfTime.msecsTo(otherTime));
2783 }
2784 
2785 
2786 /*!
2787     \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec specification) const
2788 
2789     Returns a copy of this datetime configured to use the given time
2790     \a specification.
2791 
2792     \sa timeSpec(), toUTC(), toLocalTime()
2793 */
2794 
toTimeSpec(Qt::TimeSpec spec) const2795 QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
2796 {
2797     if ((d->spec == QDateTimePrivate::UTC) == (spec == Qt::UTC))
2798         return *this;
2799 
2800     QDateTime ret;
2801     if (spec == Qt::UTC) {
2802         d->getUTC(ret.d->date, ret.d->time);
2803         ret.d->spec = QDateTimePrivate::UTC;
2804     } else {
2805         ret.d->spec = d->getLocal(ret.d->date, ret.d->time);
2806     }
2807     return ret;
2808 }
2809 
2810 /*!
2811     Returns true if this datetime is equal to the \a other datetime;
2812     otherwise returns false.
2813 
2814     \sa operator!=()
2815 */
2816 
operator ==(const QDateTime & other) const2817 bool QDateTime::operator==(const QDateTime &other) const
2818 {
2819     if (d->spec == other.d->spec && d->utcOffset == other.d->utcOffset)
2820         return d->time == other.d->time && d->date == other.d->date;
2821     else {
2822         QDate date1, date2;
2823         QTime time1, time2;
2824 
2825         d->getUTC(date1, time1);
2826         other.d->getUTC(date2, time2);
2827         return time1 == time2 && date1 == date2;
2828     }
2829 }
2830 
2831 /*!
2832     \fn bool QDateTime::operator!=(const QDateTime &other) const
2833 
2834     Returns true if this datetime is different from the \a other
2835     datetime; otherwise returns false.
2836 
2837     Two datetimes are different if either the date, the time, or the
2838     time zone components are different.
2839 
2840     \sa operator==()
2841 */
2842 
2843 /*!
2844     Returns true if this datetime is earlier than the \a other
2845     datetime; otherwise returns false.
2846 */
2847 
operator <(const QDateTime & other) const2848 bool QDateTime::operator<(const QDateTime &other) const
2849 {
2850     if (d->spec == other.d->spec && d->spec != QDateTimePrivate::OffsetFromUTC) {
2851         if (d->date != other.d->date)
2852             return d->date < other.d->date;
2853         return d->time < other.d->time;
2854     } else {
2855         QDate date1, date2;
2856         QTime time1, time2;
2857         d->getUTC(date1, time1);
2858         other.d->getUTC(date2, time2);
2859         if (date1 != date2)
2860             return date1 < date2;
2861         return time1 < time2;
2862     }
2863 }
2864 
2865 /*!
2866     \fn bool QDateTime::operator<=(const QDateTime &other) const
2867 
2868     Returns true if this datetime is earlier than or equal to the
2869     \a other datetime; otherwise returns false.
2870 */
2871 
2872 /*!
2873     \fn bool QDateTime::operator>(const QDateTime &other) const
2874 
2875     Returns true if this datetime is later than the \a other datetime;
2876     otherwise returns false.
2877 */
2878 
2879 /*!
2880     \fn bool QDateTime::operator>=(const QDateTime &other) const
2881 
2882     Returns true if this datetime is later than or equal to the
2883     \a other datetime; otherwise returns false.
2884 */
2885 
2886 /*!
2887     \fn QDateTime QDateTime::currentDateTime()
2888     Returns the current datetime, as reported by the system clock, in
2889     the local time zone.
2890 
2891     \sa currentDateTimeUtc(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
2892 */
2893 
2894 /*!
2895     \fn QDateTime QDateTime::currentDateTimeUtc()
2896     \since 4.7
2897     Returns the current datetime, as reported by the system clock, in
2898     UTC.
2899 
2900     \sa currentDateTime(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
2901 */
2902 
2903 /*!
2904     \fn qint64 QDateTime::currentMSecsSinceEpoch()
2905     \since 4.7
2906 
2907     Returns the number of milliseconds since 1970-01-01T00:00:00 Universal
2908     Coordinated Time. This number is like the POSIX time_t variable, but
2909     expressed in milliseconds instead.
2910 
2911     \sa currentDateTime(), currentDateTimeUtc(), toTime_t(), toTimeSpec()
2912 */
2913 
msecsFromDecomposed(int hour,int minute,int sec,int msec=0)2914 static inline uint msecsFromDecomposed(int hour, int minute, int sec, int msec = 0)
2915 {
2916     return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + 1000 * sec + msec;
2917 }
2918 
2919 #if defined(Q_OS_WIN)
currentDate()2920 QDate QDate::currentDate()
2921 {
2922     QDate d;
2923     SYSTEMTIME st;
2924     memset(&st, 0, sizeof(SYSTEMTIME));
2925     GetLocalTime(&st);
2926     d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
2927     return d;
2928 }
2929 
currentTime()2930 QTime QTime::currentTime()
2931 {
2932     QTime ct;
2933     SYSTEMTIME st;
2934     memset(&st, 0, sizeof(SYSTEMTIME));
2935     GetLocalTime(&st);
2936     ct.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
2937 #if defined(Q_OS_WINCE)
2938     ct.startTick = GetTickCount() % MSECS_PER_DAY;
2939 #endif
2940     return ct;
2941 }
2942 
currentDateTime()2943 QDateTime QDateTime::currentDateTime()
2944 {
2945     QDate d;
2946     QTime t;
2947     SYSTEMTIME st;
2948     memset(&st, 0, sizeof(SYSTEMTIME));
2949     GetLocalTime(&st);
2950     d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
2951     t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
2952     return QDateTime(d, t);
2953 }
2954 
currentDateTimeUtc()2955 QDateTime QDateTime::currentDateTimeUtc()
2956 {
2957     QDate d;
2958     QTime t;
2959     SYSTEMTIME st;
2960     memset(&st, 0, sizeof(SYSTEMTIME));
2961     GetSystemTime(&st);
2962     d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
2963     t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
2964     return QDateTime(d, t, Qt::UTC);
2965 }
2966 
currentMSecsSinceEpoch()2967 qint64 QDateTime::currentMSecsSinceEpoch()
2968 {
2969     QDate d;
2970     QTime t;
2971     SYSTEMTIME st;
2972     memset(&st, 0, sizeof(SYSTEMTIME));
2973     GetSystemTime(&st);
2974 
2975     return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
2976             qint64(julianDayFromGregorianDate(st.wYear, st.wMonth, st.wDay)
2977                    - julianDayFromGregorianDate(1970, 1, 1)) * Q_INT64_C(86400000);
2978 }
2979 
2980 #elif defined(Q_OS_SYMBIAN)
currentDate()2981 QDate QDate::currentDate()
2982 {
2983     QDate d;
2984     TTime localTime;
2985     localTime.HomeTime();
2986     TDateTime localDateTime = localTime.DateTime();
2987     // months and days are zero indexed
2988     d.jd = julianDayFromDate(localDateTime.Year(), localDateTime.Month() + 1, localDateTime.Day() + 1 );
2989     return d;
2990 }
2991 
currentTime()2992 QTime QTime::currentTime()
2993 {
2994     QTime ct;
2995     TTime localTime;
2996     localTime.HomeTime();
2997     TDateTime localDateTime = localTime.DateTime();
2998     ct.mds = msecsFromDecomposed(localDateTime.Hour(), localDateTime.Minute(),
2999                                  localDateTime.Second(), localDateTime.MicroSecond() / 1000);
3000     return ct;
3001 }
3002 
currentDateTime()3003 QDateTime QDateTime::currentDateTime()
3004 {
3005     QDate d;
3006     QTime ct;
3007     TTime localTime;
3008     localTime.HomeTime();
3009     TDateTime localDateTime = localTime.DateTime();
3010     // months and days are zero indexed
3011     d.jd = julianDayFromDate(localDateTime.Year(), localDateTime.Month() + 1, localDateTime.Day() + 1);
3012     ct.mds = msecsFromDecomposed(localDateTime.Hour(), localDateTime.Minute(),
3013                                  localDateTime.Second(), localDateTime.MicroSecond() / 1000);
3014     return QDateTime(d, ct);
3015 }
3016 
currentDateTimeUtc()3017 QDateTime QDateTime::currentDateTimeUtc()
3018 {
3019     QDate d;
3020     QTime ct;
3021     TTime gmTime;
3022     gmTime.UniversalTime();
3023     TDateTime gmtDateTime = gmTime.DateTime();
3024     // months and days are zero indexed
3025     d.jd = julianDayFromDate(gmtDateTime.Year(), gmtDateTime.Month() + 1, gmtDateTime.Day() + 1);
3026     ct.mds = msecsFromDecomposed(gmtDateTime.Hour(), gmtDateTime.Minute(),
3027                                  gmtDateTime.Second(), gmtDateTime.MicroSecond() / 1000);
3028     return QDateTime(d, ct, Qt::UTC);
3029 }
3030 
currentMSecsSinceEpoch()3031 qint64 QDateTime::currentMSecsSinceEpoch()
3032 {
3033     QDate d;
3034     QTime ct;
3035     TTime gmTime;
3036     gmTime.UniversalTime();
3037     TDateTime gmtDateTime = gmTime.DateTime();
3038 
3039     // according to the documentation, the value is:
3040     // "a date and time as a number of microseconds since midnight, January 1st, 0 AD nominal Gregorian"
3041     qint64 value = gmTime.Int64();
3042 
3043     // whereas 1970-01-01T00:00:00 is (in the same representation):
3044     //   ((1970 * 365) + (1970 / 4) - (1970 / 100) + (1970 / 400) - 13) * 86400 * 1000000
3045     static const qint64 unixEpoch = Q_INT64_C(0xdcddb30f2f8000);
3046 
3047     return (value - unixEpoch) / 1000;
3048 }
3049 
3050 #elif defined(Q_OS_UNIX)
currentDate()3051 QDate QDate::currentDate()
3052 {
3053     QDate d;
3054     // posix compliant system
3055     time_t ltime;
3056     time(&ltime);
3057     struct tm *t = 0;
3058 
3059 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3060     // use the reentrant version of localtime() where available
3061     tzset();
3062     struct tm res;
3063     t = localtime_r(&ltime, &res);
3064 #else
3065     t = localtime(&ltime);
3066 #endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
3067 
3068     d.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
3069     return d;
3070 }
3071 
currentTime()3072 QTime QTime::currentTime()
3073 {
3074     QTime ct;
3075     // posix compliant system
3076     struct timeval tv;
3077     gettimeofday(&tv, 0);
3078     time_t ltime = tv.tv_sec;
3079     struct tm *t = 0;
3080 
3081 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3082     // use the reentrant version of localtime() where available
3083     tzset();
3084     struct tm res;
3085     t = localtime_r(&ltime, &res);
3086 #else
3087     t = localtime(&ltime);
3088 #endif
3089     Q_CHECK_PTR(t);
3090 
3091     ct.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
3092     return ct;
3093 }
3094 
currentDateTime()3095 QDateTime QDateTime::currentDateTime()
3096 {
3097     // posix compliant system
3098     // we have milliseconds
3099     struct timeval tv;
3100     gettimeofday(&tv, 0);
3101     time_t ltime = tv.tv_sec;
3102     struct tm *t = 0;
3103 
3104 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3105     // use the reentrant version of localtime() where available
3106     tzset();
3107     struct tm res;
3108     t = localtime_r(&ltime, &res);
3109 #else
3110     t = localtime(&ltime);
3111 #endif
3112 
3113     QDateTime dt;
3114     dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
3115 
3116     dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
3117     dt.d->spec = t->tm_isdst > 0  ? QDateTimePrivate::LocalDST :
3118                  t->tm_isdst == 0 ? QDateTimePrivate::LocalStandard :
3119                  QDateTimePrivate::LocalUnknown;
3120     return dt;
3121 }
3122 
currentDateTimeUtc()3123 QDateTime QDateTime::currentDateTimeUtc()
3124 {
3125     // posix compliant system
3126     // we have milliseconds
3127     struct timeval tv;
3128     gettimeofday(&tv, 0);
3129     time_t ltime = tv.tv_sec;
3130     struct tm *t = 0;
3131 
3132 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3133     // use the reentrant version of localtime() where available
3134     struct tm res;
3135     t = gmtime_r(&ltime, &res);
3136 #else
3137     t = gmtime(&ltime);
3138 #endif
3139 
3140     QDateTime dt;
3141     dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
3142 
3143     dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
3144     dt.d->spec = QDateTimePrivate::UTC;
3145     return dt;
3146 }
3147 
currentMSecsSinceEpoch()3148 qint64 QDateTime::currentMSecsSinceEpoch()
3149 {
3150     // posix compliant system
3151     // we have milliseconds
3152     struct timeval tv;
3153     gettimeofday(&tv, 0);
3154     return qint64(tv.tv_sec) * Q_INT64_C(1000) + tv.tv_usec / 1000;
3155 }
3156 
3157 #else
3158 #error "What system is this?"
3159 #endif
3160 
3161 /*!
3162   \since 4.2
3163 
3164   Returns a datetime whose date and time are the number of \a seconds
3165   that have passed since 1970-01-01T00:00:00, Coordinated Universal
3166   Time (Qt::UTC). On systems that do not support time zones, the time
3167   will be set as if local time were Qt::UTC.
3168 
3169   \sa toTime_t(), setTime_t()
3170 */
fromTime_t(uint seconds)3171 QDateTime QDateTime::fromTime_t(uint seconds)
3172 {
3173     QDateTime d;
3174     d.setTime_t(seconds);
3175     return d;
3176 }
3177 
3178 /*!
3179   \since 4.7
3180 
3181   Returns a datetime whose date and time are the number of milliseconds, \a msecs,
3182   that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
3183   Time (Qt::UTC). On systems that do not support time zones, the time
3184   will be set as if local time were Qt::UTC.
3185 
3186   Note that there are possible values for \a msecs that lie outside the valid
3187   range of QDateTime, both negative and positive. The behavior of this
3188   function is undefined for those values.
3189 
3190   \sa toTime_t(), setTime_t()
3191 */
fromMSecsSinceEpoch(qint64 msecs)3192 QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
3193 {
3194     QDateTime d;
3195     d.setMSecsSinceEpoch(msecs);
3196     return d;
3197 }
3198 
3199 /*!
3200  \since 4.4
3201  \internal
3202 
3203  Sets the offset from UTC to \a seconds, and also sets timeSpec() to
3204  Qt::OffsetFromUTC.
3205 
3206  The maximum and minimum offset is 14 positive or negative hours.  If
3207  \a seconds is larger or smaller than that, the result is undefined.
3208 
3209  0 as offset is identical to UTC. Therefore, if \a seconds is 0, the
3210  timeSpec() will be set to Qt::UTC. Hence the UTC offset always
3211  relates to UTC, and can never relate to local time.
3212 
3213  \sa isValid(), utcOffset()
3214  */
setUtcOffset(int seconds)3215 void QDateTime::setUtcOffset(int seconds)
3216 {
3217     detach();
3218 
3219     /* The motivation to also setting d->spec is to ensure that the QDateTime
3220      * instance stay in well-defined states all the time, instead of that
3221      * we instruct the user to ensure it. */
3222     if(seconds == 0)
3223         d->spec = QDateTimePrivate::UTC;
3224     else
3225         d->spec = QDateTimePrivate::OffsetFromUTC;
3226 
3227     /* Even if seconds is 0 we assign it to utcOffset. */
3228     d->utcOffset = seconds;
3229 }
3230 
3231 /*!
3232  \since 4.4
3233  \internal
3234 
3235  Returns the UTC offset in seconds. If the timeSpec() isn't
3236  Qt::OffsetFromUTC, 0 is returned. However, since 0 is a valid UTC
3237  offset the return value of this function cannot be used to determine
3238  whether a utcOffset() is used or is valid, timeSpec() must be
3239  checked.
3240 
3241  Likewise, if this QDateTime() is invalid or if timeSpec() isn't
3242  Qt::OffsetFromUTC, 0 is returned.
3243 
3244  The UTC offset only applies if the timeSpec() is Qt::OffsetFromUTC.
3245 
3246  \sa isValid(), setUtcOffset()
3247  */
utcOffset() const3248 int QDateTime::utcOffset() const
3249 {
3250     if(isValid() && d->spec == QDateTimePrivate::OffsetFromUTC)
3251         return d->utcOffset;
3252     else
3253         return 0;
3254 }
3255 
3256 #ifndef QT_NO_DATESTRING
3257 
fromShortMonthName(const QString & monthName)3258 static int fromShortMonthName(const QString &monthName)
3259 {
3260     // Assume that English monthnames are the default
3261     for (int i = 0; i < 12; ++i) {
3262         if (monthName == QLatin1String(qt_shortMonthNames[i]))
3263             return i + 1;
3264     }
3265     // If English names can't be found, search the localized ones
3266     for (int i = 1; i <= 12; ++i) {
3267         if (monthName == QDate::shortMonthName(i))
3268             return i;
3269     }
3270     return -1;
3271 }
3272 
3273 /*!
3274     \fn QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
3275 
3276     Returns the QDateTime represented by the \a string, using the
3277     \a format given, or an invalid datetime if this is not possible.
3278 
3279     Note for Qt::TextDate: It is recommended that you use the
3280     English short month names (e.g. "Jan"). Although localized month
3281     names can also be used, they depend on the user's locale settings.
3282 */
fromString(const QString & s,Qt::DateFormat f)3283 QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
3284 {
3285     if (s.isEmpty()) {
3286         return QDateTime();
3287     }
3288 
3289     switch (f) {
3290     case Qt::ISODate: {
3291         QString tmp = s;
3292         Qt::TimeSpec ts = Qt::LocalTime;
3293         const QDate date = QDate::fromString(tmp.left(10), Qt::ISODate);
3294         if (tmp.size() == 10)
3295             return QDateTime(date);
3296 
3297         tmp = tmp.mid(11);
3298 
3299         // Recognize UTC specifications
3300         if (tmp.endsWith(QLatin1Char('Z'))) {
3301             ts = Qt::UTC;
3302             tmp.chop(1);
3303         }
3304 
3305         // Recognize timezone specifications
3306         QRegExp rx(QLatin1String("[+-]"));
3307         if (tmp.contains(rx)) {
3308             int idx = tmp.indexOf(rx);
3309             QString tmp2 = tmp.mid(idx);
3310             tmp = tmp.left(idx);
3311             bool ok = true;
3312             int ntzhour = 1;
3313             int ntzminute = 3;
3314             if ( tmp2.indexOf(QLatin1Char(':')) == 3 )
3315                ntzminute = 4;
3316             const int tzhour(tmp2.mid(ntzhour, 2).toInt(&ok));
3317             const int tzminute(tmp2.mid(ntzminute, 2).toInt(&ok));
3318             QTime tzt(tzhour, tzminute);
3319             int utcOffset = (tzt.hour() * 60 + tzt.minute()) * 60;
3320             if ( utcOffset != 0 ) {
3321                 ts = Qt::OffsetFromUTC;
3322                 QDateTime dt(date, QTime::fromString(tmp, Qt::ISODate), ts);
3323                 dt.setUtcOffset( utcOffset * (tmp2.startsWith(QLatin1Char('-')) ? -1 : 1) );
3324                 return dt;
3325             }
3326         }
3327         return QDateTime(date, QTime::fromString(tmp, Qt::ISODate), ts);
3328     }
3329     case Qt::SystemLocaleDate:
3330     case Qt::SystemLocaleShortDate:
3331     case Qt::SystemLocaleLongDate:
3332         return fromString(s, QLocale::system().dateTimeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
3333                                                                                             : QLocale::ShortFormat));
3334     case Qt::LocaleDate:
3335     case Qt::DefaultLocaleShortDate:
3336     case Qt::DefaultLocaleLongDate:
3337         return fromString(s, QLocale().dateTimeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
3338                                                                                      : QLocale::ShortFormat));
3339 #if !defined(QT_NO_TEXTDATE)
3340     case Qt::TextDate: {
3341         QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
3342 
3343         if ((parts.count() < 5) || (parts.count() > 6)) {
3344             return QDateTime();
3345         }
3346 
3347         // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974"
3348         int month = -1, day = -1;
3349         bool ok;
3350 
3351         month = fromShortMonthName(parts.at(1));
3352         if (month != -1) {
3353             day = parts.at(2).toInt(&ok);
3354             if (!ok)
3355                 day = -1;
3356         }
3357 
3358         if (month == -1 || day == -1) {
3359             // first variant failed, lets try the other
3360             month = fromShortMonthName(parts.at(2));
3361             if (month != -1) {
3362                 QString dayStr = parts.at(1);
3363                 if (dayStr.endsWith(QLatin1Char('.'))) {
3364                     dayStr.chop(1);
3365                     day = dayStr.toInt(&ok);
3366                     if (!ok)
3367                         day = -1;
3368                 } else {
3369                     day = -1;
3370                 }
3371             }
3372         }
3373 
3374         if (month == -1 || day == -1) {
3375             // both variants failed, give up
3376             return QDateTime();
3377         }
3378 
3379         int year;
3380         QStringList timeParts = parts.at(3).split(QLatin1Char(':'));
3381         if ((timeParts.count() == 3) || (timeParts.count() == 2)) {
3382             year = parts.at(4).toInt(&ok);
3383             if (!ok)
3384                 return QDateTime();
3385         } else {
3386             timeParts = parts.at(4).split(QLatin1Char(':'));
3387             if ((timeParts.count() != 3) && (timeParts.count() != 2))
3388                 return QDateTime();
3389             year = parts.at(3).toInt(&ok);
3390             if (!ok)
3391                 return QDateTime();
3392         }
3393 
3394         int hour = timeParts.at(0).toInt(&ok);
3395         if (!ok) {
3396             return QDateTime();
3397         }
3398 
3399         int minute = timeParts.at(1).toInt(&ok);
3400         if (!ok) {
3401             return QDateTime();
3402         }
3403 
3404         int second = (timeParts.count() > 2) ? timeParts.at(2).toInt(&ok) : 0;
3405         if (!ok) {
3406             return QDateTime();
3407         }
3408 
3409         QDate date(year, month, day);
3410         QTime time(hour, minute, second);
3411 
3412         if (parts.count() == 5)
3413             return QDateTime(date, time, Qt::LocalTime);
3414 
3415         QString tz = parts.at(5);
3416         if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
3417             return QDateTime();
3418         QDateTime dt(date, time, Qt::UTC);
3419         if (tz.length() > 3) {
3420             int tzoffset = 0;
3421             QChar sign = tz.at(3);
3422             if ((sign != QLatin1Char('+'))
3423                 && (sign != QLatin1Char('-'))) {
3424                 return QDateTime();
3425             }
3426             int tzhour = tz.mid(4, 2).toInt(&ok);
3427             if (!ok)
3428                 return QDateTime();
3429             int tzminute = tz.mid(6).toInt(&ok);
3430             if (!ok)
3431                 return QDateTime();
3432             tzoffset = (tzhour*60 + tzminute) * 60;
3433             if (sign == QLatin1Char('-'))
3434                 tzoffset = -tzoffset;
3435             dt.setUtcOffset(tzoffset);
3436         }
3437         return dt.toLocalTime();
3438     }
3439 #endif //QT_NO_TEXTDATE
3440     }
3441 
3442     return QDateTime();
3443 }
3444 
3445 /*!
3446     \fn QDateTime::fromString(const QString &string, const QString &format)
3447 
3448     Returns the QDateTime represented by the \a string, using the \a
3449     format given, or an invalid datetime if the string cannot be parsed.
3450 
3451     These expressions may be used for the date part of the format string:
3452 
3453     \table
3454     \header \i Expression \i Output
3455     \row \i d \i the day as number without a leading zero (1 to 31)
3456     \row \i dd \i the day as number with a leading zero (01 to 31)
3457     \row \i ddd
3458             \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
3459             Uses QDate::shortDayName().
3460     \row \i dddd
3461             \i the long localized day name (e.g. 'Monday' to 'Sunday').
3462             Uses QDate::longDayName().
3463     \row \i M \i the month as number without a leading zero (1-12)
3464     \row \i MM \i the month as number with a leading zero (01-12)
3465     \row \i MMM
3466             \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
3467             Uses QDate::shortMonthName().
3468     \row \i MMMM
3469             \i the long localized month name (e.g. 'January' to 'December').
3470             Uses QDate::longMonthName().
3471     \row \i yy \i the year as two digit number (00-99)
3472     \row \i yyyy \i the year as four digit number
3473     \endtable
3474 
3475     \note Unlike the other version of this function, day and month names must
3476     be given in the user's local language. It is only possible to use the English
3477     names if the user's language is English.
3478 
3479     These expressions may be used for the time part of the format string:
3480 
3481     \table
3482     \header \i Expression \i Output
3483     \row \i h
3484             \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
3485     \row \i hh
3486             \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
3487     \row \i H
3488             \i the hour without a leading zero (0 to 23, even with AM/PM display)
3489     \row \i HH
3490             \i the hour with a leading zero (00 to 23, even with AM/PM display)
3491     \row \i m \i the minute without a leading zero (0 to 59)
3492     \row \i mm \i the minute with a leading zero (00 to 59)
3493     \row \i s \i the second without a leading zero (0 to 59)
3494     \row \i ss \i the second with a leading zero (00 to 59)
3495     \row \i z \i the milliseconds without leading zeroes (0 to 999)
3496     \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
3497     \row \i AP or A
3498          \i interpret as an AM/PM time. \e AP must be either "AM" or "PM".
3499     \row \i ap or a
3500          \i Interpret as an AM/PM time. \e ap must be either "am" or "pm".
3501     \endtable
3502 
3503     All other input characters will be treated as text. Any sequence
3504     of characters that are enclosed in singlequotes will also be
3505     treated as text and not be used as an expression.
3506 
3507     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 12
3508 
3509     If the format is not satisfied an invalid QDateTime is returned.
3510     The expressions that don't have leading zeroes (d, M, h, m, s, z) will be
3511     greedy. This means that they will use two digits even if this will
3512     put them outside the range and/or leave too few digits for other
3513     sections.
3514 
3515     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 13
3516 
3517     This could have meant 1 January 00:30.00 but the M will grab
3518     two digits.
3519 
3520     For any field that is not represented in the format the following
3521     defaults are used:
3522 
3523     \table
3524     \header \i Field  \i Default value
3525     \row    \i Year   \i 1900
3526     \row    \i Month  \i 1 (January)
3527     \row    \i Day    \i 1
3528     \row    \i Hour   \i 0
3529     \row    \i Minute \i 0
3530     \row    \i Second \i 0
3531     \endtable
3532 
3533     For example:
3534 
3535     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 14
3536 
3537     \sa QDate::fromString() QTime::fromString() QDate::toString()
3538     QDateTime::toString() QTime::toString()
3539 */
3540 
fromString(const QString & string,const QString & format)3541 QDateTime QDateTime::fromString(const QString &string, const QString &format)
3542 {
3543 #ifndef QT_BOOTSTRAPPED
3544     QTime time;
3545     QDate date;
3546 
3547     QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
3548     if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
3549         return QDateTime(date, time);
3550 #else
3551     Q_UNUSED(string);
3552     Q_UNUSED(format);
3553 #endif
3554     return QDateTime(QDate(), QTime(-1, -1, -1));
3555 }
3556 
3557 #endif // QT_NO_DATESTRING
3558 /*!
3559     \fn QDateTime QDateTime::toLocalTime() const
3560 
3561     Returns a datetime containing the date and time information in
3562     this datetime, but specified using the Qt::LocalTime definition.
3563 
3564     \sa toTimeSpec()
3565 */
3566 
3567 /*!
3568     \fn QDateTime QDateTime::toUTC() const
3569 
3570     Returns a datetime containing the date and time information in
3571     this datetime, but specified using the Qt::UTC definition.
3572 
3573     \sa toTimeSpec()
3574 */
3575 
3576 /*! \internal
3577  */
detach()3578 void QDateTime::detach()
3579 {
3580     d.detach();
3581 }
3582 
3583 /*****************************************************************************
3584   Date/time stream functions
3585  *****************************************************************************/
3586 
3587 #ifndef QT_NO_DATASTREAM
3588 /*!
3589     \relates QDate
3590 
3591     Writes the \a date to stream \a out.
3592 
3593     \sa {Serializing Qt Data Types}
3594 */
3595 
operator <<(QDataStream & out,const QDate & date)3596 QDataStream &operator<<(QDataStream &out, const QDate &date)
3597 {
3598     return out << (quint32)(date.jd);
3599 }
3600 
3601 /*!
3602     \relates QDate
3603 
3604     Reads a date from stream \a in into the \a date.
3605 
3606     \sa {Serializing Qt Data Types}
3607 */
3608 
operator >>(QDataStream & in,QDate & date)3609 QDataStream &operator>>(QDataStream &in, QDate &date)
3610 {
3611     quint32 jd;
3612     in >> jd;
3613     date.jd = jd;
3614     return in;
3615 }
3616 
3617 /*!
3618     \relates QTime
3619 
3620     Writes \a time to stream \a out.
3621 
3622     \sa {Serializing Qt Data Types}
3623 */
3624 
operator <<(QDataStream & out,const QTime & time)3625 QDataStream &operator<<(QDataStream &out, const QTime &time)
3626 {
3627     return out << quint32(time.mds);
3628 }
3629 
3630 /*!
3631     \relates QTime
3632 
3633     Reads a time from stream \a in into the given \a time.
3634 
3635     \sa {Serializing Qt Data Types}
3636 */
3637 
operator >>(QDataStream & in,QTime & time)3638 QDataStream &operator>>(QDataStream &in, QTime &time)
3639 {
3640     quint32 ds;
3641     in >> ds;
3642     time.mds = int(ds);
3643     return in;
3644 }
3645 
3646 /*!
3647     \relates QDateTime
3648 
3649     Writes \a dateTime to the \a out stream.
3650 
3651     \sa {Serializing Qt Data Types}
3652 */
operator <<(QDataStream & out,const QDateTime & dateTime)3653 QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
3654 {
3655     out << dateTime.d->date << dateTime.d->time;
3656     if (out.version() >= 7)
3657         out << (qint8)dateTime.d->spec;
3658     return out;
3659 }
3660 
3661 /*!
3662     \relates QDateTime
3663 
3664     Reads a datetime from the stream \a in into \a dateTime.
3665 
3666     \sa {Serializing Qt Data Types}
3667 */
3668 
operator >>(QDataStream & in,QDateTime & dateTime)3669 QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
3670 {
3671     dateTime.detach();
3672 
3673     qint8 ts = (qint8)QDateTimePrivate::LocalUnknown;
3674     in >> dateTime.d->date >> dateTime.d->time;
3675     if (in.version() >= 7)
3676         in >> ts;
3677     dateTime.d->spec = (QDateTimePrivate::Spec)ts;
3678     return in;
3679 }
3680 #endif // QT_NO_DATASTREAM
3681 
3682 
3683 /*!
3684     \fn QString QDate::monthName(int month)
3685 
3686     Use shortMonthName() instead.
3687 */
3688 
3689 /*!
3690     \fn QString QDate::dayName(int weekday)
3691 
3692     Use shortDayName() instead.
3693 */
3694 
3695 /*!
3696     \fn bool QDate::leapYear(int year)
3697 
3698     Use isLeapYear() instead.
3699 */
3700 
3701 /*!
3702     \fn QDate QDate::currentDate(Qt::TimeSpec spec)
3703 
3704     If \a spec is Qt::LocalTime, use the currentDate() overload that
3705     takes no parameters instead; otherwise, use
3706     QDateTime::currentDateTime().
3707 
3708     \oldcode
3709         QDate localDate = QDate::currentDate(Qt::LocalTime);
3710         QDate utcDate = QDate::currentDate(Qt::UTC);
3711     \newcode
3712         QDate localDate = QDate::currentDate();
3713         QDate utcDate = QDateTime::currentDateTime().toUTC().date();
3714     \endcode
3715 
3716     \sa QDateTime::toUTC()
3717 */
3718 
3719 /*!
3720     \fn QTime QTime::currentTime(Qt::TimeSpec specification)
3721 
3722     Returns the current time for the given \a specification.
3723 
3724     To replace uses of this function where the \a specification is Qt::LocalTime,
3725     use the currentDate() overload that takes no parameters instead; otherwise,
3726     use QDateTime::currentDateTime() and convert the result to a UTC measurement.
3727 
3728     \oldcode
3729         QTime localTime = QTime::currentTime(Qt::LocalTime);
3730         QTime utcTime = QTime::currentTime(Qt::UTC);
3731     \newcode
3732         QTime localTime = QTime::currentTime();
3733         QTime utcTime = QTimeTime::currentDateTime().toUTC().time();
3734     \endcode
3735 
3736     \sa QDateTime::toUTC()
3737 */
3738 
3739 /*!
3740     \fn void QDateTime::setTime_t(uint secsSince1Jan1970UTC, Qt::TimeSpec spec)
3741 
3742     Use the single-argument overload of setTime_t() instead.
3743 */
3744 
3745 /*!
3746     \fn QDateTime QDateTime::currentDateTime(Qt::TimeSpec spec)
3747 
3748     Use the currentDateTime() overload that takes no parameters
3749     instead.
3750 */
3751 
3752 // checks if there is an unqoted 'AP' or 'ap' in the string
hasUnquotedAP(const QString & f)3753 static bool hasUnquotedAP(const QString &f)
3754 {
3755     const QLatin1Char quote('\'');
3756     bool inquote = false;
3757     const int max = f.size();
3758     for (int i=0; i<max; ++i) {
3759         if (f.at(i) == quote) {
3760             inquote = !inquote;
3761         } else if (!inquote && f.at(i).toUpper() == QLatin1Char('A')) {
3762             return true;
3763         }
3764     }
3765     return false;
3766 }
3767 
3768 #ifndef QT_NO_DATESTRING
3769 /*****************************************************************************
3770   Some static function used by QDate, QTime and QDateTime
3771 *****************************************************************************/
3772 
3773 // Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens
getFmtString(const QString & f,const QTime * dt=0,const QDate * dd=0,bool am_pm=false)3774 static QString getFmtString(const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = false)
3775 {
3776     if (f.isEmpty())
3777         return QString();
3778 
3779     QString buf = f;
3780     int removed = 0;
3781 
3782     if (dt) {
3783         if (f.startsWith(QLatin1String("hh")) || f.startsWith(QLatin1String("HH"))) {
3784             const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
3785             if (hour12 && dt->hour() > 12)
3786                 buf = QString::number(dt->hour() - 12).rightJustified(2, QLatin1Char('0'), true);
3787             else if (hour12 && dt->hour() == 0)
3788                 buf = QLatin1String("12");
3789             else
3790                 buf = QString::number(dt->hour()).rightJustified(2, QLatin1Char('0'), true);
3791             removed = 2;
3792         } else if (f.at(0) == QLatin1Char('h') || f.at(0) == QLatin1Char('H')) {
3793             const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
3794             if (hour12 && dt->hour() > 12)
3795                 buf = QString::number(dt->hour() - 12);
3796             else if (hour12 && dt->hour() == 0)
3797                 buf = QLatin1String("12");
3798             else
3799                 buf = QString::number(dt->hour());
3800             removed = 1;
3801         } else if (f.startsWith(QLatin1String("mm"))) {
3802             buf = QString::number(dt->minute()).rightJustified(2, QLatin1Char('0'), true);
3803             removed = 2;
3804         } else if (f.at(0) == (QLatin1Char('m'))) {
3805             buf = QString::number(dt->minute());
3806             removed = 1;
3807         } else if (f.startsWith(QLatin1String("ss"))) {
3808             buf = QString::number(dt->second()).rightJustified(2, QLatin1Char('0'), true);
3809             removed = 2;
3810         } else if (f.at(0) == QLatin1Char('s')) {
3811             buf = QString::number(dt->second());
3812         } else if (f.startsWith(QLatin1String("zzz"))) {
3813             buf = QString::number(dt->msec()).rightJustified(3, QLatin1Char('0'), true);
3814             removed = 3;
3815         } else if (f.at(0) == QLatin1Char('z')) {
3816             buf = QString::number(dt->msec());
3817             removed = 1;
3818         } else if (f.at(0).toUpper() == QLatin1Char('A')) {
3819             const bool upper = f.at(0) == QLatin1Char('A');
3820             buf = dt->hour() < 12 ? QLatin1String("am") : QLatin1String("pm");
3821             if (upper)
3822                 buf = buf.toUpper();
3823             if (f.size() > 1 && f.at(1).toUpper() == QLatin1Char('P') &&
3824                 f.at(0).isUpper() == f.at(1).isUpper()) {
3825                 removed = 2;
3826             } else {
3827                 removed = 1;
3828             }
3829         }
3830     }
3831 
3832     if (dd) {
3833         if (f.startsWith(QLatin1String("dddd"))) {
3834             buf = dd->longDayName(dd->dayOfWeek());
3835             removed = 4;
3836         } else if (f.startsWith(QLatin1String("ddd"))) {
3837             buf = dd->shortDayName(dd->dayOfWeek());
3838             removed = 3;
3839         } else if (f.startsWith(QLatin1String("dd"))) {
3840             buf = QString::number(dd->day()).rightJustified(2, QLatin1Char('0'), true);
3841             removed = 2;
3842         } else if (f.at(0) == QLatin1Char('d')) {
3843             buf = QString::number(dd->day());
3844             removed = 1;
3845         } else if (f.startsWith(QLatin1String("MMMM"))) {
3846             buf = dd->longMonthName(dd->month());
3847             removed = 4;
3848         } else if (f.startsWith(QLatin1String("MMM"))) {
3849             buf = dd->shortMonthName(dd->month());
3850             removed = 3;
3851         } else if (f.startsWith(QLatin1String("MM"))) {
3852             buf = QString::number(dd->month()).rightJustified(2, QLatin1Char('0'), true);
3853             removed = 2;
3854         } else if (f.at(0) == QLatin1Char('M')) {
3855             buf = QString::number(dd->month());
3856             removed = 1;
3857         } else if (f.startsWith(QLatin1String("yyyy"))) {
3858             const int year = dd->year();
3859             buf = QString::number(qAbs(year)).rightJustified(4, QLatin1Char('0'));
3860             if(year > 0)
3861                 removed = 4;
3862             else
3863             {
3864                 buf.prepend(QLatin1Char('-'));
3865                 removed = 5;
3866             }
3867 
3868         } else if (f.startsWith(QLatin1String("yy"))) {
3869             buf = QString::number(dd->year()).right(2).rightJustified(2, QLatin1Char('0'));
3870             removed = 2;
3871         }
3872     }
3873     if (removed == 0 || removed >= f.size()) {
3874         return buf;
3875     }
3876 
3877     return buf + getFmtString(f.mid(removed), dt, dd, am_pm);
3878 }
3879 
3880 // Parses the format string and uses getFmtString to get the values for the tokens. Ret
fmtDateTime(const QString & f,const QTime * dt,const QDate * dd)3881 static QString fmtDateTime(const QString& f, const QTime* dt, const QDate* dd)
3882 {
3883     const QLatin1Char quote('\'');
3884     if (f.isEmpty())
3885         return QString();
3886     if (dt && !dt->isValid())
3887         return QString();
3888     if (dd && !dd->isValid())
3889         return QString();
3890 
3891     const bool ap = hasUnquotedAP(f);
3892 
3893     QString buf;
3894     QString frm;
3895     QChar status(QLatin1Char('0'));
3896 
3897     for (int i = 0; i < (int)f.length(); ++i) {
3898         if (f.at(i) == quote) {
3899             if (status == quote) {
3900                 if (i > 0 && f.at(i - 1) == quote)
3901                     buf += QLatin1Char('\'');
3902                 status = QLatin1Char('0');
3903             } else {
3904                 if (!frm.isEmpty()) {
3905                     buf += getFmtString(frm, dt, dd, ap);
3906                     frm.clear();
3907                 }
3908                 status = quote;
3909             }
3910         } else if (status == quote) {
3911             buf += f.at(i);
3912         } else if (f.at(i) == status) {
3913             if ((ap) && ((f.at(i) == QLatin1Char('P')) || (f.at(i) == QLatin1Char('p'))))
3914                 status = QLatin1Char('0');
3915             frm += f.at(i);
3916         } else {
3917             buf += getFmtString(frm, dt, dd, ap);
3918             frm.clear();
3919             if ((f.at(i) == QLatin1Char('h')) || (f.at(i) == QLatin1Char('m'))
3920                 || (f.at(i) == QLatin1Char('H'))
3921                 || (f.at(i) == QLatin1Char('s')) || (f.at(i) == QLatin1Char('z'))) {
3922                 status = f.at(i);
3923                 frm += f.at(i);
3924             } else if ((f.at(i) == QLatin1Char('d')) || (f.at(i) == QLatin1Char('M')) || (f.at(i) == QLatin1Char('y'))) {
3925                 status = f.at(i);
3926                 frm += f.at(i);
3927             } else if ((ap) && (f.at(i) == QLatin1Char('A'))) {
3928                 status = QLatin1Char('P');
3929                 frm += f.at(i);
3930             } else  if((ap) && (f.at(i) == QLatin1Char('a'))) {
3931                 status = QLatin1Char('p');
3932                 frm += f.at(i);
3933             } else {
3934                 buf += f.at(i);
3935                 status = QLatin1Char('0');
3936             }
3937         }
3938     }
3939 
3940     buf += getFmtString(frm, dt, dd, ap);
3941 
3942     return buf;
3943 }
3944 #endif // QT_NO_DATESTRING
3945 
3946 #ifdef Q_OS_WIN
3947 static const int LowerYear = 1980;
3948 #else
3949 static const int LowerYear = 1970;
3950 #endif
3951 static const int UpperYear = 2037;
3952 
adjustDate(QDate date)3953 static QDate adjustDate(QDate date)
3954 {
3955     QDate lowerLimit(LowerYear, 1, 2);
3956     QDate upperLimit(UpperYear, 12, 30);
3957 
3958     if (date > lowerLimit && date < upperLimit)
3959         return date;
3960 
3961     int month = date.month();
3962     int day = date.day();
3963 
3964     // neither 1970 nor 2037 are leap years, so make sure date isn't Feb 29
3965     if (month == 2 && day == 29)
3966         --day;
3967 
3968     if (date < lowerLimit)
3969         date.setDate(LowerYear, month, day);
3970     else
3971         date.setDate(UpperYear, month, day);
3972 
3973     return date;
3974 }
3975 
utcToLocal(QDate & date,QTime & time)3976 static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time)
3977 {
3978     QDate fakeDate = adjustDate(date);
3979 
3980     // won't overflow because of fakeDate
3981     time_t secsSince1Jan1970UTC = toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime().msecsTo(time)) / 1000;
3982     tm *brokenDown = 0;
3983 
3984 #if defined(Q_OS_WINCE)
3985     tm res;
3986     FILETIME utcTime = time_tToFt(secsSince1Jan1970UTC);
3987     FILETIME resultTime;
3988     FileTimeToLocalFileTime(&utcTime , &resultTime);
3989     SYSTEMTIME sysTime;
3990     FileTimeToSystemTime(&resultTime , &sysTime);
3991 
3992     res.tm_sec = sysTime.wSecond;
3993     res.tm_min = sysTime.wMinute;
3994     res.tm_hour = sysTime.wHour;
3995     res.tm_mday = sysTime.wDay;
3996     res.tm_mon = sysTime.wMonth - 1;
3997     res.tm_year = sysTime.wYear - 1900;
3998     brokenDown = &res;
3999 #elif defined(Q_OS_SYMBIAN)
4000     // months and days are zero index based
4001     _LIT(KUnixEpoch, "19700000:000000.000000");
4002     TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
4003     TTime epochTTime;
4004     TInt err = epochTTime.Set(KUnixEpoch);
4005     tm res;
4006     if(err == KErrNone) {
4007         TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
4008         CTrapCleanup *cleanup = CTrapCleanup::New();    // needed to avoid crashes in apps that previously were able to use this function in static data initialization
4009         TRAP(err,
4010             RTz tz;
4011             User::LeaveIfError(tz.Connect());
4012             CleanupClosePushL(tz);
4013             CTzId *tzId = tz.GetTimeZoneIdL();
4014             CleanupStack::PushL(tzId);
4015             res.tm_isdst = tz.IsDaylightSavingOnL(*tzId,utcTTime);
4016             User::LeaveIfError(tz.ConvertToLocalTime(utcTTime));
4017             CleanupStack::PopAndDestroy(tzId);
4018             CleanupStack::PopAndDestroy(&tz));
4019         delete cleanup;
4020         if (KErrNone == err) {
4021             TDateTime localDateTime = utcTTime.DateTime();
4022             res.tm_sec = localDateTime.Second();
4023             res.tm_min = localDateTime.Minute();
4024             res.tm_hour = localDateTime.Hour();
4025             res.tm_mday = localDateTime.Day() + 1; // non-zero based index for tm struct
4026             res.tm_mon = localDateTime.Month();
4027             res.tm_year = localDateTime.Year() - 1900;
4028             // Symbian's timezone server doesn't know how to handle DST before year 1997
4029             if (res.tm_year < 97)
4030                 res.tm_isdst = -1;
4031             brokenDown = &res;
4032         }
4033     }
4034 #elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
4035     // use the reentrant version of localtime() where available
4036     tzset();
4037     tm res;
4038     brokenDown = localtime_r(&secsSince1Jan1970UTC, &res);
4039 #elif defined(_MSC_VER) && _MSC_VER >= 1400
4040     tm res;
4041     if (!_localtime64_s(&res, &secsSince1Jan1970UTC))
4042         brokenDown = &res;
4043 #else
4044     brokenDown = localtime(&secsSince1Jan1970UTC);
4045 #endif
4046     if (!brokenDown) {
4047         date = QDate(1970, 1, 1);
4048         time = QTime();
4049         return QDateTimePrivate::LocalUnknown;
4050     } else {
4051         int deltaDays = fakeDate.daysTo(date);
4052         date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
4053         time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
4054         date = date.addDays(deltaDays);
4055         if (brokenDown->tm_isdst > 0)
4056             return QDateTimePrivate::LocalDST;
4057         else if (brokenDown->tm_isdst < 0)
4058             return QDateTimePrivate::LocalUnknown;
4059         else
4060             return QDateTimePrivate::LocalStandard;
4061     }
4062 }
4063 
localToUtc(QDate & date,QTime & time,int isdst)4064 static void localToUtc(QDate &date, QTime &time, int isdst)
4065 {
4066     if (!date.isValid())
4067         return;
4068 
4069     QDate fakeDate = adjustDate(date);
4070 
4071     tm localTM;
4072     localTM.tm_sec = time.second();
4073     localTM.tm_min = time.minute();
4074     localTM.tm_hour = time.hour();
4075     localTM.tm_mday = fakeDate.day();
4076     localTM.tm_mon = fakeDate.month() - 1;
4077     localTM.tm_year = fakeDate.year() - 1900;
4078     localTM.tm_isdst = (int)isdst;
4079 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
4080     time_t secsSince1Jan1970UTC = (toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime().msecsTo(time)) / 1000);
4081 #else
4082 #if defined(Q_OS_WIN)
4083     _tzset();
4084 #endif
4085     time_t secsSince1Jan1970UTC = mktime(&localTM);
4086 #ifdef Q_OS_QNX
4087     //mktime sometimes fails on QNX. Following workaround converts the date and time then manually
4088     if (secsSince1Jan1970UTC == (time_t)-1) {
4089         QDateTime tempTime = QDateTime(date, time, Qt::UTC);;
4090         tempTime = tempTime.addMSecs(timezone * 1000);
4091         date = tempTime.date();
4092         time = tempTime.time();
4093         return;
4094     }
4095 #endif
4096 #endif
4097     tm *brokenDown = 0;
4098 #if defined(Q_OS_WINCE)
4099     tm res;
4100     FILETIME localTime = time_tToFt(secsSince1Jan1970UTC);
4101     SYSTEMTIME sysTime;
4102     FileTimeToSystemTime(&localTime, &sysTime);
4103     FILETIME resultTime;
4104     LocalFileTimeToFileTime(&localTime , &resultTime);
4105     FileTimeToSystemTime(&resultTime , &sysTime);
4106     res.tm_sec = sysTime.wSecond;
4107     res.tm_min = sysTime.wMinute;
4108     res.tm_hour = sysTime.wHour;
4109     res.tm_mday = sysTime.wDay;
4110     res.tm_mon = sysTime.wMonth - 1;
4111     res.tm_year = sysTime.wYear - 1900;
4112     res.tm_isdst = (int)isdst;
4113     brokenDown = &res;
4114 #elif defined(Q_OS_SYMBIAN)
4115     // months and days are zero index based
4116     _LIT(KUnixEpoch, "19700000:000000.000000");
4117     TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
4118     TTime epochTTime;
4119     TInt err = epochTTime.Set(KUnixEpoch);
4120     tm res;
4121     if(err == KErrNone) {
4122         TTime localTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
4123         RTz tz;
4124         if (KErrNone == tz.Connect()) {
4125             if (KErrNone == tz.ConvertToUniversalTime(localTTime)) {
4126                 TDateTime utcDateTime = localTTime.DateTime();
4127                 res.tm_sec = utcDateTime.Second();
4128                 res.tm_min = utcDateTime.Minute();
4129                 res.tm_hour = utcDateTime.Hour();
4130                 res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
4131                 res.tm_mon = utcDateTime.Month();
4132                 res.tm_year = utcDateTime.Year() - 1900;
4133                 res.tm_isdst = (int)isdst;
4134                 brokenDown = &res;
4135             }
4136         tz.Close();
4137         }
4138     }
4139 #elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
4140     // use the reentrant version of gmtime() where available
4141     tm res;
4142     brokenDown = gmtime_r(&secsSince1Jan1970UTC, &res);
4143 #elif defined(_MSC_VER) && _MSC_VER >= 1400
4144     tm res;
4145     if (!_gmtime64_s(&res, &secsSince1Jan1970UTC))
4146         brokenDown = &res;
4147 #else
4148     brokenDown = gmtime(&secsSince1Jan1970UTC);
4149 #endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
4150     if (!brokenDown) {
4151         date = QDate(1970, 1, 1);
4152         time = QTime();
4153     } else {
4154         int deltaDays = fakeDate.daysTo(date);
4155         date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
4156         time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
4157         date = date.addDays(deltaDays);
4158     }
4159 }
4160 
getLocal(QDate & outDate,QTime & outTime) const4161 QDateTimePrivate::Spec QDateTimePrivate::getLocal(QDate &outDate, QTime &outTime) const
4162 {
4163     outDate = date;
4164     outTime = time;
4165     if (spec == QDateTimePrivate::UTC)
4166         return utcToLocal(outDate, outTime);
4167     return spec;
4168 }
4169 
getUTC(QDate & outDate,QTime & outTime) const4170 void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const
4171 {
4172     outDate = date;
4173     outTime = time;
4174     const bool isOffset = spec == QDateTimePrivate::OffsetFromUTC;
4175 
4176     if (spec != QDateTimePrivate::UTC && !isOffset)
4177         localToUtc(outDate, outTime, (int)spec);
4178 
4179     if (isOffset)
4180         addMSecs(outDate, outTime, -(qint64(utcOffset) * 1000));
4181 }
4182 
4183 #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
operator <<(QDebug dbg,const QDate & date)4184 QDebug operator<<(QDebug dbg, const QDate &date)
4185 {
4186     dbg.nospace() << "QDate(" << date.toString() << ')';
4187     return dbg.space();
4188 }
4189 
operator <<(QDebug dbg,const QTime & time)4190 QDebug operator<<(QDebug dbg, const QTime &time)
4191 {
4192     dbg.nospace() << "QTime(" << time.toString() << ')';
4193     return dbg.space();
4194 }
4195 
operator <<(QDebug dbg,const QDateTime & date)4196 QDebug operator<<(QDebug dbg, const QDateTime &date)
4197 {
4198     dbg.nospace() << "QDateTime(" << date.toString() << ')';
4199     return dbg.space();
4200 }
4201 #endif
4202 
4203 #ifndef QT_BOOTSTRAPPED
4204 
4205 /*!
4206   \internal
4207   Gets the digit from a datetime. E.g.
4208 
4209   QDateTime var(QDate(2004, 02, 02));
4210   int digit = getDigit(var, Year);
4211   // digit = 2004
4212 */
4213 
getDigit(const QDateTime & t,int index) const4214 int QDateTimeParser::getDigit(const QDateTime &t, int index) const
4215 {
4216     if (index < 0 || index >= sectionNodes.size()) {
4217 #ifndef QT_NO_DATESTRING
4218         qWarning("QDateTimeParser::getDigit() Internal error (%s %d)",
4219                  qPrintable(t.toString()), index);
4220 #else
4221         qWarning("QDateTimeParser::getDigit() Internal error (%d)", index);
4222 #endif
4223         return -1;
4224     }
4225     const SectionNode &node = sectionNodes.at(index);
4226     switch (node.type) {
4227     case Hour24Section: case Hour12Section: return t.time().hour();
4228     case MinuteSection: return t.time().minute();
4229     case SecondSection: return t.time().second();
4230     case MSecSection: return t.time().msec();
4231     case YearSection2Digits:
4232     case YearSection: return t.date().year();
4233     case MonthSection: return t.date().month();
4234     case DaySection: return t.date().day();
4235     case DayOfWeekSection: return t.date().day();
4236     case AmPmSection: return t.time().hour() > 11 ? 1 : 0;
4237 
4238     default: break;
4239     }
4240 
4241 #ifndef QT_NO_DATESTRING
4242     qWarning("QDateTimeParser::getDigit() Internal error 2 (%s %d)",
4243              qPrintable(t.toString()), index);
4244 #else
4245     qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index);
4246 #endif
4247     return -1;
4248 }
4249 
4250 /*!
4251   \internal
4252   Sets a digit in a datetime. E.g.
4253 
4254   QDateTime var(QDate(2004, 02, 02));
4255   int digit = getDigit(var, Year);
4256   // digit = 2004
4257   setDigit(&var, Year, 2005);
4258   digit = getDigit(var, Year);
4259   // digit = 2005
4260 */
4261 
setDigit(QDateTime & v,int index,int newVal) const4262 bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
4263 {
4264     if (index < 0 || index >= sectionNodes.size()) {
4265 #ifndef QT_NO_DATESTRING
4266         qWarning("QDateTimeParser::setDigit() Internal error (%s %d %d)",
4267                  qPrintable(v.toString()), index, newVal);
4268 #else
4269         qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal);
4270 #endif
4271         return false;
4272     }
4273     const SectionNode &node = sectionNodes.at(index);
4274 
4275     int year, month, day, hour, minute, second, msec;
4276     year = v.date().year();
4277     month = v.date().month();
4278     day = v.date().day();
4279     hour = v.time().hour();
4280     minute = v.time().minute();
4281     second = v.time().second();
4282     msec = v.time().msec();
4283 
4284     switch (node.type) {
4285     case Hour24Section: case Hour12Section: hour = newVal; break;
4286     case MinuteSection: minute = newVal; break;
4287     case SecondSection: second = newVal; break;
4288     case MSecSection: msec = newVal; break;
4289     case YearSection2Digits:
4290     case YearSection: year = newVal; break;
4291     case MonthSection: month = newVal; break;
4292     case DaySection:
4293     case DayOfWeekSection:
4294         if (newVal > 31) {
4295             // have to keep legacy behavior. setting the
4296             // date to 32 should return false. Setting it
4297             // to 31 for february should return true
4298             return false;
4299         }
4300         day = newVal;
4301         break;
4302     case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
4303     default:
4304         qWarning("QDateTimeParser::setDigit() Internal error (%s)",
4305                  qPrintable(sectionName(node.type)));
4306         break;
4307     }
4308 
4309     if (!(node.type & (DaySection|DayOfWeekSection))) {
4310         if (day < cachedDay)
4311             day = cachedDay;
4312         const int max = QDate(year, month, 1).daysInMonth();
4313         if (day > max) {
4314             day = max;
4315         }
4316     }
4317     if (QDate::isValid(year, month, day) && QTime::isValid(hour, minute, second, msec)) {
4318         v = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
4319         return true;
4320     }
4321     return false;
4322 }
4323 
4324 
4325 
4326 /*!
4327   \
4328 
4329   Returns the absolute maximum for a section
4330 */
4331 
absoluteMax(int s,const QDateTime & cur) const4332 int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
4333 {
4334     const SectionNode &sn = sectionNode(s);
4335     switch (sn.type) {
4336     case Hour24Section:
4337     case Hour12Section: return 23; // this is special-cased in
4338                                    // parseSection. We want it to be
4339                                    // 23 for the stepBy case.
4340     case MinuteSection:
4341     case SecondSection: return 59;
4342     case MSecSection: return 999;
4343     case YearSection2Digits:
4344     case YearSection: return 9999; // sectionMaxSize will prevent
4345                                    // people from typing in a larger
4346                                    // number in count == 2 sections.
4347                                    // stepBy() will work on real years anyway
4348     case MonthSection: return 12;
4349     case DaySection:
4350     case DayOfWeekSection: return cur.isValid() ? cur.date().daysInMonth() : 31;
4351     case AmPmSection: return 1;
4352     default: break;
4353     }
4354     qWarning("QDateTimeParser::absoluteMax() Internal error (%s)",
4355              qPrintable(sectionName(sn.type)));
4356     return -1;
4357 }
4358 
4359 /*!
4360   \internal
4361 
4362   Returns the absolute minimum for a section
4363 */
4364 
absoluteMin(int s) const4365 int QDateTimeParser::absoluteMin(int s) const
4366 {
4367     const SectionNode &sn = sectionNode(s);
4368     switch (sn.type) {
4369     case Hour24Section:
4370     case Hour12Section:
4371     case MinuteSection:
4372     case SecondSection:
4373     case MSecSection:
4374     case YearSection2Digits:
4375     case YearSection: return 0;
4376     case MonthSection:
4377     case DaySection:
4378     case DayOfWeekSection: return 1;
4379     case AmPmSection: return 0;
4380     default: break;
4381     }
4382     qWarning("QDateTimeParser::absoluteMin() Internal error (%s, %0x)",
4383              qPrintable(sectionName(sn.type)), sn.type);
4384     return -1;
4385 }
4386 
4387 /*!
4388   \internal
4389 
4390   Returns the sectionNode for the Section \a s.
4391 */
4392 
sectionNode(int sectionIndex) const4393 const QDateTimeParser::SectionNode &QDateTimeParser::sectionNode(int sectionIndex) const
4394 {
4395     if (sectionIndex < 0) {
4396         switch (sectionIndex) {
4397         case FirstSectionIndex:
4398             return first;
4399         case LastSectionIndex:
4400             return last;
4401         case NoSectionIndex:
4402             return none;
4403         }
4404     } else if (sectionIndex < sectionNodes.size()) {
4405         return sectionNodes.at(sectionIndex);
4406     }
4407 
4408     qWarning("QDateTimeParser::sectionNode() Internal error (%d)",
4409              sectionIndex);
4410     return none;
4411 }
4412 
sectionType(int sectionIndex) const4413 QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const
4414 {
4415     return sectionNode(sectionIndex).type;
4416 }
4417 
4418 
4419 /*!
4420   \internal
4421 
4422   Returns the starting position for section \a s.
4423 */
4424 
sectionPos(int sectionIndex) const4425 int QDateTimeParser::sectionPos(int sectionIndex) const
4426 {
4427     return sectionPos(sectionNode(sectionIndex));
4428 }
4429 
sectionPos(const SectionNode & sn) const4430 int QDateTimeParser::sectionPos(const SectionNode &sn) const
4431 {
4432     switch (sn.type) {
4433     case FirstSection: return 0;
4434     case LastSection: return displayText().size() - 1;
4435     default: break;
4436     }
4437     if (sn.pos == -1) {
4438         qWarning("QDateTimeParser::sectionPos Internal error (%s)", qPrintable(sectionName(sn.type)));
4439         return -1;
4440     }
4441     return sn.pos;
4442 }
4443 
4444 
4445 /*!
4446   \internal helper function for parseFormat. removes quotes that are
4447   not escaped and removes the escaping on those that are escaped
4448 
4449 */
4450 
unquote(const QString & str)4451 static QString unquote(const QString &str)
4452 {
4453     const QChar quote(QLatin1Char('\''));
4454     const QChar slash(QLatin1Char('\\'));
4455     const QChar zero(QLatin1Char('0'));
4456     QString ret;
4457     QChar status(zero);
4458     const int max = str.size();
4459     for (int i=0; i<max; ++i) {
4460         if (str.at(i) == quote) {
4461             if (status != quote) {
4462                 status = quote;
4463             } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
4464                 ret[ret.size() - 1] = quote;
4465             } else {
4466                 status = zero;
4467             }
4468         } else {
4469             ret += str.at(i);
4470         }
4471     }
4472     return ret;
4473 }
4474 /*!
4475   \internal
4476 
4477   Parses the format \a newFormat. If successful, returns true and
4478   sets up the format. Else keeps the old format and returns false.
4479 
4480 */
4481 
countRepeat(const QString & str,int index,int maxCount)4482 static inline int countRepeat(const QString &str, int index, int maxCount)
4483 {
4484     int count = 1;
4485     const QChar ch(str.at(index));
4486     const int max = qMin(index + maxCount, str.size());
4487     while (index + count < max && str.at(index + count) == ch) {
4488         ++count;
4489     }
4490     return count;
4491 }
4492 
appendSeparator(QStringList * list,const QString & string,int from,int size,int lastQuote)4493 static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote)
4494 {
4495     QString str(string.mid(from, size));
4496     if (lastQuote >= from)
4497         str = unquote(str);
4498     list->append(str);
4499 }
4500 
4501 
parseFormat(const QString & newFormat)4502 bool QDateTimeParser::parseFormat(const QString &newFormat)
4503 {
4504     const QLatin1Char quote('\'');
4505     const QLatin1Char slash('\\');
4506     const QLatin1Char zero('0');
4507     if (newFormat == displayFormat && !newFormat.isEmpty()) {
4508         return true;
4509     }
4510 
4511     QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData());
4512 
4513     QVector<SectionNode> newSectionNodes;
4514     Sections newDisplay = 0;
4515     QStringList newSeparators;
4516     int i, index = 0;
4517     int add = 0;
4518     QChar status(zero);
4519     const int max = newFormat.size();
4520     int lastQuote = -1;
4521     for (i = 0; i<max; ++i) {
4522         if (newFormat.at(i) == quote) {
4523             lastQuote = i;
4524             ++add;
4525             if (status != quote) {
4526                 status = quote;
4527             } else if (newFormat.at(i - 1) != slash) {
4528                 status = zero;
4529             }
4530         } else if (status != quote) {
4531             const char sect = newFormat.at(i).toLatin1();
4532             switch (sect) {
4533             case 'H':
4534             case 'h':
4535                 if (parserType != QVariant::Date) {
4536                     const Section hour = (sect == 'h') ? Hour12Section : Hour24Section;
4537                     const SectionNode sn = { hour, i - add, countRepeat(newFormat, i, 2) };
4538                     newSectionNodes.append(sn);
4539                     appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4540                     i += sn.count - 1;
4541                     index = i + 1;
4542                     newDisplay |= hour;
4543                 }
4544                 break;
4545             case 'm':
4546                 if (parserType != QVariant::Date) {
4547                     const SectionNode sn = { MinuteSection, i - add, countRepeat(newFormat, i, 2) };
4548                     newSectionNodes.append(sn);
4549                     appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4550                     i += sn.count - 1;
4551                     index = i + 1;
4552                     newDisplay |= MinuteSection;
4553                 }
4554                 break;
4555             case 's':
4556                 if (parserType != QVariant::Date) {
4557                     const SectionNode sn = { SecondSection, i - add, countRepeat(newFormat, i, 2) };
4558                     newSectionNodes.append(sn);
4559                     appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4560                     i += sn.count - 1;
4561                     index = i + 1;
4562                     newDisplay |= SecondSection;
4563                 }
4564                 break;
4565 
4566             case 'z':
4567                 if (parserType != QVariant::Date) {
4568                     const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3 };
4569                     newSectionNodes.append(sn);
4570                     appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4571                     i += sn.count - 1;
4572                     index = i + 1;
4573                     newDisplay |= MSecSection;
4574                 }
4575                 break;
4576             case 'A':
4577             case 'a':
4578                 if (parserType != QVariant::Date) {
4579                     const bool cap = (sect == 'A');
4580                     const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0) };
4581                     newSectionNodes.append(sn);
4582                     appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4583                     newDisplay |= AmPmSection;
4584                     if (i + 1 < newFormat.size()
4585                         && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
4586                         ++i;
4587                     }
4588                     index = i + 1;
4589                 }
4590                 break;
4591             case 'y':
4592                 if (parserType != QVariant::Time) {
4593                     const int repeat = countRepeat(newFormat, i, 4);
4594                     if (repeat >= 2) {
4595                         const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits,
4596                                                  i - add, repeat == 4 ? 4 : 2 };
4597                         newSectionNodes.append(sn);
4598                         appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4599                         i += sn.count - 1;
4600                         index = i + 1;
4601                         newDisplay |= sn.type;
4602                     }
4603                 }
4604                 break;
4605             case 'M':
4606                 if (parserType != QVariant::Time) {
4607                     const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4) };
4608                     newSectionNodes.append(sn);
4609                     newSeparators.append(unquote(newFormat.mid(index, i - index)));
4610                     i += sn.count - 1;
4611                     index = i + 1;
4612                     newDisplay |= MonthSection;
4613                 }
4614                 break;
4615             case 'd':
4616                 if (parserType != QVariant::Time) {
4617                     const int repeat = countRepeat(newFormat, i, 4);
4618                     const SectionNode sn = { repeat >= 3 ? DayOfWeekSection : DaySection, i - add, repeat };
4619                     newSectionNodes.append(sn);
4620                     appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4621                     i += sn.count - 1;
4622                     index = i + 1;
4623                     newDisplay |= sn.type;
4624                 }
4625                 break;
4626 
4627             default:
4628                 break;
4629             }
4630         }
4631     }
4632     if (newSectionNodes.isEmpty() && context == DateTimeEdit) {
4633         return false;
4634     }
4635 
4636     if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
4637         const int max = newSectionNodes.size();
4638         for (int i=0; i<max; ++i) {
4639             SectionNode &node = newSectionNodes[i];
4640             if (node.type == Hour12Section)
4641                 node.type = Hour24Section;
4642         }
4643     }
4644 
4645     if (index < newFormat.size()) {
4646         appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote);
4647     } else {
4648         newSeparators.append(QString());
4649     }
4650 
4651     displayFormat = newFormat;
4652     separators = newSeparators;
4653     sectionNodes = newSectionNodes;
4654     display = newDisplay;
4655     last.pos = -1;
4656 
4657 //     for (int i=0; i<sectionNodes.size(); ++i) {
4658 //         QDTPDEBUG << sectionName(sectionNodes.at(i).type) << sectionNodes.at(i).count;
4659 //     }
4660 
4661     QDTPDEBUG << newFormat << displayFormat;
4662     QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData());
4663 
4664     return true;
4665 }
4666 
4667 /*!
4668   \internal
4669 
4670   Returns the size of section \a s.
4671 */
4672 
sectionSize(int sectionIndex) const4673 int QDateTimeParser::sectionSize(int sectionIndex) const
4674 {
4675     if (sectionIndex < 0)
4676         return 0;
4677 
4678     if (sectionIndex >= sectionNodes.size()) {
4679         qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex);
4680         return -1;
4681     }
4682     if (sectionIndex == sectionNodes.size() - 1) {
4683         return displayText().size() - sectionPos(sectionIndex) - separators.last().size();
4684     } else {
4685         return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex)
4686             - separators.at(sectionIndex + 1).size();
4687     }
4688 }
4689 
4690 
sectionMaxSize(Section s,int count) const4691 int QDateTimeParser::sectionMaxSize(Section s, int count) const
4692 {
4693 #ifndef QT_NO_TEXTDATE
4694     int mcount = 12;
4695 #endif
4696 
4697     switch (s) {
4698     case FirstSection:
4699     case NoSection:
4700     case LastSection: return 0;
4701 
4702     case AmPmSection: {
4703         const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(),
4704                                   getAmPmText(PmText, LowerCase).size());
4705         const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(),
4706                                   getAmPmText(PmText, UpperCase).size());
4707         return qMin(4, qMin(lowerMax, upperMax));
4708     }
4709 
4710     case Hour24Section:
4711     case Hour12Section:
4712     case MinuteSection:
4713     case SecondSection:
4714     case DaySection: return 2;
4715     case DayOfWeekSection:
4716 #ifdef QT_NO_TEXTDATE
4717         return 2;
4718 #else
4719         mcount = 7;
4720         // fall through
4721 #endif
4722     case MonthSection:
4723         if (count <= 2)
4724             return 2;
4725 
4726 #ifdef QT_NO_TEXTDATE
4727         return 2;
4728 #else
4729         {
4730             int ret = 0;
4731             const QLocale l = locale();
4732             for (int i=1; i<=mcount; ++i) {
4733                 const QString str = (s == MonthSection
4734                                      ? l.monthName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat)
4735                                      : l.dayName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat));
4736                 ret = qMax(str.size(), ret);
4737             }
4738             return ret;
4739         }
4740 #endif
4741     case MSecSection: return 3;
4742     case YearSection: return 4;
4743     case YearSection2Digits: return 2;
4744 
4745     case CalendarPopupSection:
4746     case Internal:
4747     case TimeSectionMask:
4748     case DateSectionMask:
4749         qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s",
4750                  sectionName(s).toLatin1().constData());
4751 
4752     case NoSectionIndex:
4753     case FirstSectionIndex:
4754     case LastSectionIndex:
4755     case CalendarPopupIndex:
4756         // these cases can't happen
4757         break;
4758     }
4759     return -1;
4760 }
4761 
4762 
sectionMaxSize(int index) const4763 int QDateTimeParser::sectionMaxSize(int index) const
4764 {
4765     const SectionNode &sn = sectionNode(index);
4766     return sectionMaxSize(sn.type, sn.count);
4767 }
4768 
4769 /*!
4770   \internal
4771 
4772   Returns the text of section \a s. This function operates on the
4773   arg text rather than edit->text().
4774 */
4775 
4776 
sectionText(const QString & text,int sectionIndex,int index) const4777 QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const
4778 {
4779     const SectionNode &sn = sectionNode(sectionIndex);
4780     switch (sn.type) {
4781     case NoSectionIndex:
4782     case FirstSectionIndex:
4783     case LastSectionIndex:
4784         return QString();
4785     default: break;
4786     }
4787 
4788     return text.mid(index, sectionSize(sectionIndex));
4789 }
4790 
sectionText(int sectionIndex) const4791 QString QDateTimeParser::sectionText(int sectionIndex) const
4792 {
4793     const SectionNode &sn = sectionNode(sectionIndex);
4794     switch (sn.type) {
4795     case NoSectionIndex:
4796     case FirstSectionIndex:
4797     case LastSectionIndex:
4798         return QString();
4799     default: break;
4800     }
4801 
4802     return displayText().mid(sn.pos, sectionSize(sectionIndex));
4803 }
4804 
4805 
4806 #ifndef QT_NO_TEXTDATE
4807 /*!
4808   \internal:skipToNextSection
4809 
4810   Parses the part of \a text that corresponds to \a s and returns
4811   the value of that field. Sets *stateptr to the right state if
4812   stateptr != 0.
4813 */
4814 
parseSection(const QDateTime & currentValue,int sectionIndex,QString & text,int & cursorPosition,int index,State & state,int * usedptr) const4815 int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
4816                                   QString &text, int &cursorPosition, int index,
4817                                   State &state, int *usedptr) const
4818 {
4819     state = Invalid;
4820     int num = 0;
4821     const SectionNode &sn = sectionNode(sectionIndex);
4822     if ((sn.type & Internal) == Internal) {
4823         qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
4824                  qPrintable(sectionName(sn.type)), sectionIndex);
4825         return -1;
4826     }
4827 
4828     const int sectionmaxsize = sectionMaxSize(sectionIndex);
4829     QString sectiontext = text.mid(index, sectionmaxsize);
4830     int sectiontextSize = sectiontext.size();
4831 
4832     QDTPDEBUG << "sectionValue for" << sectionName(sn.type)
4833               << "with text" << text << "and st" << sectiontext
4834               << text.mid(index, sectionmaxsize)
4835               << index;
4836 
4837     int used = 0;
4838     switch (sn.type) {
4839     case AmPmSection: {
4840         const int ampm = findAmPm(sectiontext, sectionIndex, &used);
4841         switch (ampm) {
4842         case AM: // sectiontext == AM
4843         case PM: // sectiontext == PM
4844             num = ampm;
4845             state = Acceptable;
4846             break;
4847         case PossibleAM: // sectiontext => AM
4848         case PossiblePM: // sectiontext => PM
4849             num = ampm - 2;
4850             state = Intermediate;
4851             break;
4852         case PossibleBoth: // sectiontext => AM|PM
4853             num = 0;
4854             state = Intermediate;
4855             break;
4856         case Neither:
4857             state = Invalid;
4858             QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1";
4859             break;
4860         default:
4861             QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm);
4862             break;
4863         }
4864         if (state != Invalid) {
4865             QString str = text;
4866             text.replace(index, used, sectiontext.left(used));
4867         }
4868         break; }
4869     case MonthSection:
4870     case DayOfWeekSection:
4871         if (sn.count >= 3) {
4872             if (sn.type == MonthSection) {
4873                 int min = 1;
4874                 const QDate minDate = getMinimum().date();
4875                 if (currentValue.date().year() == minDate.year()) {
4876                     min = minDate.month();
4877                 }
4878                 num = findMonth(sectiontext.toLower(), min, sectionIndex, &sectiontext, &used);
4879             } else {
4880                 num = findDay(sectiontext.toLower(), 1, sectionIndex, &sectiontext, &used);
4881             }
4882 
4883             if (num != -1) {
4884                 state = (used == sectiontext.size() ? Acceptable : Intermediate);
4885                 QString str = text;
4886                 text.replace(index, used, sectiontext.left(used));
4887             } else {
4888                 state = Intermediate;
4889             }
4890             break; }
4891         // fall through
4892     case DaySection:
4893     case YearSection:
4894     case YearSection2Digits:
4895     case Hour12Section:
4896     case Hour24Section:
4897     case MinuteSection:
4898     case SecondSection:
4899     case MSecSection: {
4900         if (sectiontextSize == 0) {
4901             num = 0;
4902             used = 0;
4903             state = Intermediate;
4904         } else {
4905             const int absMax = absoluteMax(sectionIndex);
4906             QLocale loc;
4907             bool ok = true;
4908             int last = -1;
4909             used = -1;
4910 
4911             QString digitsStr(sectiontext);
4912             for (int i = 0; i < sectiontextSize; ++i) {
4913                 if (digitsStr.at(i).isSpace()) {
4914                     sectiontextSize = i;
4915                     break;
4916                 }
4917             }
4918 
4919             const int max = qMin(sectionmaxsize, sectiontextSize);
4920             for (int digits = max; digits >= 1; --digits) {
4921                 digitsStr.truncate(digits);
4922                 int tmp = (int)loc.toUInt(digitsStr, &ok, 10);
4923                 if (ok && sn.type == Hour12Section) {
4924                     if (tmp > 12) {
4925                         tmp = -1;
4926                         ok = false;
4927                     } else if (tmp == 12) {
4928                         tmp = 0;
4929                     }
4930                 }
4931                 if (ok && tmp <= absMax) {
4932                     QDTPDEBUG << sectiontext.left(digits) << tmp << digits;
4933                     last = tmp;
4934                     used = digits;
4935                     break;
4936                 }
4937             }
4938 
4939             if (last == -1) {
4940                 QChar first(sectiontext.at(0));
4941                 if (separators.at(sectionIndex + 1).startsWith(first)) {
4942                     used = 0;
4943                     state = Intermediate;
4944                 } else {
4945                     state = Invalid;
4946                     QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok;
4947                 }
4948             } else {
4949                 num += last;
4950                 const FieldInfo fi = fieldInfo(sectionIndex);
4951                 const bool done = (used == sectionmaxsize);
4952                 if (!done && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002
4953                     for (int i=used; i<sectionmaxsize; ++i) {
4954                         num *= 10;
4955                     }
4956                 }
4957                 const int absMin = absoluteMin(sectionIndex);
4958                 if (num < absMin) {
4959                     state = done ? Invalid : Intermediate;
4960                     if (done)
4961                         QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absMin;
4962                 } else if (num > absMax) {
4963                     state = Intermediate;
4964                 } else if (!done && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
4965                     if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
4966                         state = Acceptable;
4967                         const int missingZeroes = sectionmaxsize - digitsStr.size();
4968                         text.insert(index, QString().fill(QLatin1Char('0'), missingZeroes));
4969                         used = sectionmaxsize;
4970                         cursorPosition += missingZeroes;
4971                     } else {
4972                         state = Intermediate;;
4973                     }
4974                 } else {
4975                     state = Acceptable;
4976                 }
4977             }
4978         }
4979         break; }
4980     default:
4981         qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
4982                  qPrintable(sectionName(sn.type)), sectionIndex);
4983         return -1;
4984     }
4985 
4986     if (usedptr)
4987         *usedptr = used;
4988 
4989     return (state != Invalid ? num : -1);
4990 }
4991 #endif // QT_NO_TEXTDATE
4992 
4993 #ifndef QT_NO_DATESTRING
4994 /*!
4995   \internal
4996 */
4997 
parse(QString & input,int & cursorPosition,const QDateTime & currentValue,bool fixup) const4998 QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPosition,
4999                                                   const QDateTime &currentValue, bool fixup) const
5000 {
5001     const QDateTime minimum = getMinimum();
5002     const QDateTime maximum = getMaximum();
5003 
5004     State state = Acceptable;
5005 
5006     QDateTime newCurrentValue;
5007     int pos = 0;
5008     bool conflicts = false;
5009     const int sectionNodesCount = sectionNodes.size();
5010 
5011     QDTPDEBUG << "parse" << input;
5012     {
5013         int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits;
5014         getDateFromJulianDay(currentValue.date().toJulianDay(), &year, &month, &day);
5015         year2digits = year % 100;
5016         hour = currentValue.time().hour();
5017         hour12 = -1;
5018         minute = currentValue.time().minute();
5019         second = currentValue.time().second();
5020         msec = currentValue.time().msec();
5021         dayofweek = currentValue.date().dayOfWeek();
5022 
5023         ampm = -1;
5024         Sections isSet = NoSection;
5025         int num;
5026         State tmpstate;
5027 
5028         for (int index=0; state != Invalid && index<sectionNodesCount; ++index) {
5029             if (QStringRef(&input, pos, separators.at(index).size()) != separators.at(index)) {
5030                 QDTPDEBUG << "invalid because" << input.mid(pos, separators.at(index).size())
5031                           << "!=" << separators.at(index)
5032                           << index << pos << currentSectionIndex;
5033                 state = Invalid;
5034                 goto end;
5035             }
5036             pos += separators.at(index).size();
5037             sectionNodes[index].pos = pos;
5038             int *current = 0;
5039             const SectionNode sn = sectionNodes.at(index);
5040             int used;
5041 
5042             num = parseSection(currentValue, index, input, cursorPosition, pos, tmpstate, &used);
5043             QDTPDEBUG << "sectionValue" << sectionName(sectionType(index)) << input
5044                       << "pos" << pos << "used" << used << stateName(tmpstate);
5045             if (fixup && tmpstate == Intermediate && used < sn.count) {
5046                 const FieldInfo fi = fieldInfo(index);
5047                 if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
5048                     const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0'));
5049                     input.replace(pos, used, newText);
5050                     used = sn.count;
5051                 }
5052             }
5053             pos += qMax(0, used);
5054 
5055             state = qMin<State>(state, tmpstate);
5056             if (state == Intermediate && context == FromString) {
5057                 state = Invalid;
5058                 break;
5059             }
5060 
5061             QDTPDEBUG << index << sectionName(sectionType(index)) << "is set to"
5062                       << pos << "state is" << stateName(state);
5063 
5064 
5065             if (state != Invalid) {
5066                 switch (sn.type) {
5067                 case Hour24Section: current = &hour; break;
5068                 case Hour12Section: current = &hour12; break;
5069                 case MinuteSection: current = &minute; break;
5070                 case SecondSection: current = &second; break;
5071                 case MSecSection: current = &msec; break;
5072                 case YearSection: current = &year; break;
5073                 case YearSection2Digits: current = &year2digits; break;
5074                 case MonthSection: current = &month; break;
5075                 case DayOfWeekSection: current = &dayofweek; break;
5076                 case DaySection: current = &day; num = qMax<int>(1, num); break;
5077                 case AmPmSection: current = &ampm; break;
5078                 default:
5079                     qWarning("QDateTimeParser::parse Internal error (%s)",
5080                              qPrintable(sectionName(sn.type)));
5081                     break;
5082                 }
5083                 if (!current) {
5084                     qWarning("QDateTimeParser::parse Internal error 2");
5085                     return StateNode();
5086                 }
5087                 if (isSet & sn.type && *current != num) {
5088                     QDTPDEBUG << "CONFLICT " << sectionName(sn.type) << *current << num;
5089                     conflicts = true;
5090                     if (index != currentSectionIndex || num == -1) {
5091                         continue;
5092                     }
5093                 }
5094                 if (num != -1)
5095                     *current = num;
5096                 isSet |= sn.type;
5097             }
5098         }
5099 
5100         if (state != Invalid && QStringRef(&input, pos, input.size() - pos) != separators.last()) {
5101             QDTPDEBUG << "invalid because" << input.mid(pos)
5102                       << "!=" << separators.last() << pos;
5103             state = Invalid;
5104         }
5105 
5106         if (state != Invalid) {
5107             if (parserType != QVariant::Time) {
5108                 if (year % 100 != year2digits) {
5109                     switch (isSet & (YearSection2Digits|YearSection)) {
5110                     case YearSection2Digits:
5111                         year = (year / 100) * 100;
5112                         year += year2digits;
5113                         break;
5114                     case ((uint)YearSection2Digits|(uint)YearSection): {
5115                         conflicts = true;
5116                         const SectionNode &sn = sectionNode(currentSectionIndex);
5117                         if (sn.type == YearSection2Digits) {
5118                             year = (year / 100) * 100;
5119                             year += year2digits;
5120                         }
5121                         break; }
5122                     default:
5123                         break;
5124                     }
5125                 }
5126 
5127                 const QDate date(year, month, day);
5128                 const int diff = dayofweek - date.dayOfWeek();
5129                 if (diff != 0 && state == Acceptable && isSet & DayOfWeekSection) {
5130                     conflicts = isSet & DaySection;
5131                     const SectionNode &sn = sectionNode(currentSectionIndex);
5132                     if (sn.type == DayOfWeekSection || currentSectionIndex == -1) {
5133                         // dayofweek should be preferred
5134                         day += diff;
5135                         if (day <= 0) {
5136                             day += 7;
5137                         } else if (day > date.daysInMonth()) {
5138                             day -= 7;
5139                         }
5140                         QDTPDEBUG << year << month << day << dayofweek
5141                                   << diff << QDate(year, month, day).dayOfWeek();
5142                     }
5143                 }
5144                 bool needfixday = false;
5145                 if (sectionType(currentSectionIndex) & (DaySection|DayOfWeekSection)) {
5146                     cachedDay = day;
5147                 } else if (cachedDay > day) {
5148                     day = cachedDay;
5149                     needfixday = true;
5150                 }
5151 
5152                 if (!QDate::isValid(year, month, day)) {
5153                     if (day < 32) {
5154                         cachedDay = day;
5155                     }
5156                     if (day > 28 && QDate::isValid(year, month, 1)) {
5157                         needfixday = true;
5158                     }
5159                 }
5160                 if (needfixday) {
5161                     if (context == FromString) {
5162                         state = Invalid;
5163                         goto end;
5164                     }
5165                     if (state == Acceptable && fixday) {
5166                         day = qMin<int>(day, QDate(year, month, 1).daysInMonth());
5167 
5168                         const QLocale loc = locale();
5169                         for (int i=0; i<sectionNodesCount; ++i) {
5170                             if (sectionType(i) & (DaySection|DayOfWeekSection)) {
5171                                 input.replace(sectionPos(i), sectionSize(i), loc.toString(day));
5172                             }
5173                         }
5174                     } else {
5175                         state = qMin(Intermediate, state);
5176                     }
5177                 }
5178             }
5179 
5180             if (parserType != QVariant::Date) {
5181                 if (isSet & Hour12Section) {
5182                     const bool hasHour = isSet & Hour24Section;
5183                     if (ampm == -1) {
5184                         if (hasHour) {
5185                             ampm = (hour < 12 ? 0 : 1);
5186                         } else {
5187                             ampm = 0; // no way to tell if this is am or pm so I assume am
5188                         }
5189                     }
5190                     hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12);
5191                     if (!hasHour) {
5192                         hour = hour12;
5193                     } else if (hour != hour12) {
5194                         conflicts = true;
5195                     }
5196                 } else if (ampm != -1) {
5197                     if (!(isSet & (Hour24Section))) {
5198                         hour = (12 * ampm); // special case. Only ap section
5199                     } else if ((ampm == 0) != (hour < 12)) {
5200                         conflicts = true;
5201                     }
5202                 }
5203 
5204             }
5205 
5206             newCurrentValue = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
5207             QDTPDEBUG << year << month << day << hour << minute << second << msec;
5208         }
5209         QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
5210                    newCurrentValue.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
5211                    stateName(state).toLatin1().constData());
5212     }
5213 end:
5214     if (newCurrentValue.isValid()) {
5215         if (context != FromString && state != Invalid && newCurrentValue < minimum) {
5216             const QLatin1Char space(' ');
5217             if (newCurrentValue >= minimum)
5218                 qWarning("QDateTimeParser::parse Internal error 3 (%s %s)",
5219                          qPrintable(newCurrentValue.toString()), qPrintable(minimum.toString()));
5220 
5221             bool done = false;
5222             state = Invalid;
5223             for (int i=0; i<sectionNodesCount && !done; ++i) {
5224                 const SectionNode &sn = sectionNodes.at(i);
5225                 QString t = sectionText(input, i, sn.pos).toLower();
5226                 if ((t.size() < sectionMaxSize(i) && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric))
5227                     || t.contains(space)) {
5228                     switch (sn.type) {
5229                     case AmPmSection:
5230                         switch (findAmPm(t, i)) {
5231                         case AM:
5232                         case PM:
5233                             state = Acceptable;
5234                             done = true;
5235                             break;
5236                         case Neither:
5237                             state = Invalid;
5238                             done = true;
5239                             break;
5240                         case PossibleAM:
5241                         case PossiblePM:
5242                         case PossibleBoth: {
5243                             const QDateTime copy(newCurrentValue.addSecs(12 * 60 * 60));
5244                             if (copy >= minimum && copy <= maximum) {
5245                                 state = Intermediate;
5246                                 done = true;
5247                             }
5248                             break; }
5249                         }
5250                     case MonthSection:
5251                         if (sn.count >= 3) {
5252                             int tmp = newCurrentValue.date().month();
5253                             // I know the first possible month makes the date too early
5254                             while ((tmp = findMonth(t, tmp + 1, i)) != -1) {
5255                                 const QDateTime copy(newCurrentValue.addMonths(tmp - newCurrentValue.date().month()));
5256                                 if (copy >= minimum && copy <= maximum)
5257                                     break; // break out of while
5258                             }
5259                             if (tmp == -1) {
5260                                 break;
5261                             }
5262                             state = Intermediate;
5263                             done = true;
5264                             break;
5265                         }
5266                         // fallthrough
5267                     default: {
5268                         int toMin;
5269                         int toMax;
5270 
5271                         if (sn.type & TimeSectionMask) {
5272                             if (newCurrentValue.daysTo(minimum) != 0) {
5273                                 break;
5274                             }
5275                             toMin = newCurrentValue.time().msecsTo(minimum.time());
5276                             if (newCurrentValue.daysTo(maximum) > 0) {
5277                                 toMax = -1; // can't get to max
5278                             } else {
5279                                 toMax = newCurrentValue.time().msecsTo(maximum.time());
5280                             }
5281                         } else {
5282                             toMin = newCurrentValue.daysTo(minimum);
5283                             toMax = newCurrentValue.daysTo(maximum);
5284                         }
5285                         const int maxChange = QDateTimeParser::maxChange(i);
5286                         if (toMin > maxChange) {
5287                             QDTPDEBUG << "invalid because toMin > maxChange" << toMin
5288                                       << maxChange << t << newCurrentValue << minimum;
5289                             state = Invalid;
5290                             done = true;
5291                             break;
5292                         } else if (toMax > maxChange) {
5293                             toMax = -1; // can't get to max
5294                         }
5295 
5296                         const int min = getDigit(minimum, i);
5297                         if (min == -1) {
5298                             qWarning("QDateTimeParser::parse Internal error 4 (%s)",
5299                                      qPrintable(sectionName(sn.type)));
5300                             state = Invalid;
5301                             done = true;
5302                             break;
5303                         }
5304 
5305                         int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, newCurrentValue);
5306                         int pos = cursorPosition - sn.pos;
5307                         if (pos < 0 || pos >= t.size())
5308                             pos = -1;
5309                         if (!potentialValue(t.simplified(), min, max, i, newCurrentValue, pos)) {
5310                             QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max
5311                                       << sectionName(sn.type) << "returned" << toMax << toMin << pos;
5312                             state = Invalid;
5313                             done = true;
5314                             break;
5315                         }
5316                         state = Intermediate;
5317                         done = true;
5318                         break; }
5319                     }
5320                 }
5321             }
5322         } else {
5323             if (context == FromString) {
5324                 // optimization
5325                 Q_ASSERT(getMaximum().date().toJulianDay() == 4642999);
5326                 if (newCurrentValue.date().toJulianDay() > 4642999)
5327                     state = Invalid;
5328             } else {
5329                 if (newCurrentValue > getMaximum())
5330                     state = Invalid;
5331             }
5332 
5333             QDTPDEBUG << "not checking intermediate because newCurrentValue is" << newCurrentValue << getMinimum() << getMaximum();
5334         }
5335     }
5336     StateNode node;
5337     node.input = input;
5338     node.state = state;
5339     node.conflicts = conflicts;
5340     node.value = newCurrentValue.toTimeSpec(spec);
5341     text = input;
5342     return node;
5343 }
5344 #endif // QT_NO_DATESTRING
5345 
5346 #ifndef QT_NO_TEXTDATE
5347 /*!
5348   \internal finds the first possible monthname that \a str1 can
5349   match. Starting from \a index; str should already by lowered
5350 */
5351 
findMonth(const QString & str1,int startMonth,int sectionIndex,QString * usedMonth,int * used) const5352 int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex,
5353                                QString *usedMonth, int *used) const
5354 {
5355     int bestMatch = -1;
5356     int bestCount = 0;
5357     if (!str1.isEmpty()) {
5358         const SectionNode &sn = sectionNode(sectionIndex);
5359         if (sn.type != MonthSection) {
5360             qWarning("QDateTimeParser::findMonth Internal error");
5361             return -1;
5362         }
5363 
5364         QLocale::FormatType type = sn.count == 3 ? QLocale::ShortFormat : QLocale::LongFormat;
5365         QLocale l = locale();
5366 
5367         for (int month=startMonth; month<=12; ++month) {
5368             QString str2 = l.monthName(month, type).toLower();
5369 
5370             if (str1.startsWith(str2)) {
5371                 if (used) {
5372                     QDTPDEBUG << "used is set to" << str2.size();
5373                     *used = str2.size();
5374                 }
5375                 if (usedMonth)
5376                     *usedMonth = l.monthName(month, type);
5377 
5378                 return month;
5379             }
5380             if (context == FromString)
5381                 continue;
5382 
5383             const int limit = qMin(str1.size(), str2.size());
5384 
5385             QDTPDEBUG << "limit is" << limit << str1 << str2;
5386             bool equal = true;
5387             for (int i=0; i<limit; ++i) {
5388                 if (str1.at(i) != str2.at(i)) {
5389                     equal = false;
5390                     if (i > bestCount) {
5391                         bestCount = i;
5392                         bestMatch = month;
5393                     }
5394                     break;
5395                 }
5396             }
5397             if (equal) {
5398                 if (used)
5399                     *used = limit;
5400                 if (usedMonth)
5401                     *usedMonth = l.monthName(month, type);
5402                 return month;
5403             }
5404         }
5405         if (usedMonth && bestMatch != -1)
5406             *usedMonth = l.monthName(bestMatch, type);
5407     }
5408     if (used) {
5409         QDTPDEBUG << "used is set to" << bestCount;
5410         *used = bestCount;
5411     }
5412     return bestMatch;
5413 }
5414 
findDay(const QString & str1,int startDay,int sectionIndex,QString * usedDay,int * used) const5415 int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const
5416 {
5417     int bestMatch = -1;
5418     int bestCount = 0;
5419     if (!str1.isEmpty()) {
5420         const SectionNode &sn = sectionNode(sectionIndex);
5421         if (!(sn.type & (DaySection|DayOfWeekSection))) {
5422             qWarning("QDateTimeParser::findDay Internal error");
5423             return -1;
5424         }
5425         const QLocale l = locale();
5426         for (int day=startDay; day<=7; ++day) {
5427             const QString str2 = l.dayName(day, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
5428 
5429             if (str1.startsWith(str2.toLower())) {
5430                 if (used)
5431                     *used = str2.size();
5432                 if (usedDay) {
5433                     *usedDay = str2;
5434                 }
5435                 return day;
5436             }
5437             if (context == FromString)
5438                 continue;
5439 
5440             const int limit = qMin(str1.size(), str2.size());
5441             bool found = true;
5442             for (int i=0; i<limit; ++i) {
5443                 if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) {
5444                     if (i > bestCount) {
5445                         bestCount = i;
5446                         bestMatch = day;
5447                     }
5448                     found = false;
5449                     break;
5450                 }
5451 
5452             }
5453             if (found) {
5454                 if (used)
5455                     *used = limit;
5456                 if (usedDay)
5457                     *usedDay = str2;
5458 
5459                 return day;
5460             }
5461         }
5462         if (usedDay && bestMatch != -1) {
5463             *usedDay = l.dayName(bestMatch, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
5464         }
5465     }
5466     if (used)
5467         *used = bestCount;
5468 
5469     return bestMatch;
5470 }
5471 #endif // QT_NO_TEXTDATE
5472 
5473 /*!
5474   \internal
5475 
5476   returns
5477   0 if str == QDateTimeEdit::tr("AM")
5478   1 if str == QDateTimeEdit::tr("PM")
5479   2 if str can become QDateTimeEdit::tr("AM")
5480   3 if str can become QDateTimeEdit::tr("PM")
5481   4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM")
5482   -1 can't become anything sensible
5483 
5484 */
5485 
findAmPm(QString & str,int index,int * used) const5486 int QDateTimeParser::findAmPm(QString &str, int index, int *used) const
5487 {
5488     const SectionNode &s = sectionNode(index);
5489     if (s.type != AmPmSection) {
5490         qWarning("QDateTimeParser::findAmPm Internal error");
5491         return -1;
5492     }
5493     if (used)
5494         *used = str.size();
5495     if (str.trimmed().isEmpty()) {
5496         return PossibleBoth;
5497     }
5498     const QLatin1Char space(' ');
5499     int size = sectionMaxSize(index);
5500 
5501     enum {
5502         amindex = 0,
5503         pmindex = 1
5504     };
5505     QString ampm[2];
5506     ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase);
5507     ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase);
5508     for (int i=0; i<2; ++i)
5509         ampm[i].truncate(size);
5510 
5511     QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
5512 
5513     if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) {
5514         str = ampm[amindex];
5515         return AM;
5516     } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) {
5517         str = ampm[pmindex];
5518         return PM;
5519     } else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) {
5520         return Neither;
5521     }
5522     size = qMin(size, str.size());
5523 
5524     bool broken[2] = {false, false};
5525     for (int i=0; i<size; ++i) {
5526         if (str.at(i) != space) {
5527             for (int j=0; j<2; ++j) {
5528                 if (!broken[j]) {
5529                     int index = ampm[j].indexOf(str.at(i));
5530                     QDTPDEBUG << "looking for" << str.at(i)
5531                               << "in" << ampm[j] << "and got" << index;
5532                     if (index == -1) {
5533                         if (str.at(i).category() == QChar::Letter_Uppercase) {
5534                             index = ampm[j].indexOf(str.at(i).toLower());
5535                             QDTPDEBUG << "trying with" << str.at(i).toLower()
5536                                       << "in" << ampm[j] << "and got" << index;
5537                         } else if (str.at(i).category() == QChar::Letter_Lowercase) {
5538                             index = ampm[j].indexOf(str.at(i).toUpper());
5539                             QDTPDEBUG << "trying with" << str.at(i).toUpper()
5540                                       << "in" << ampm[j] << "and got" << index;
5541                         }
5542                         if (index == -1) {
5543                             broken[j] = true;
5544                             if (broken[amindex] && broken[pmindex]) {
5545                                 QDTPDEBUG << str << "didn't make it";
5546                                 return Neither;
5547                             }
5548                             continue;
5549                         } else {
5550                             str[i] = ampm[j].at(index); // fix case
5551                         }
5552                     }
5553                     ampm[j].remove(index, 1);
5554                 }
5555             }
5556         }
5557     }
5558     if (!broken[pmindex] && !broken[amindex])
5559         return PossibleBoth;
5560     return (!broken[amindex] ? PossibleAM : PossiblePM);
5561 }
5562 
5563 /*!
5564   \internal
5565   Max number of units that can be changed by this section.
5566 */
5567 
maxChange(int index) const5568 int QDateTimeParser::maxChange(int index) const
5569 {
5570     const SectionNode &sn = sectionNode(index);
5571     switch (sn.type) {
5572         // Time. unit is msec
5573     case MSecSection: return 999;
5574     case SecondSection: return 59 * 1000;
5575     case MinuteSection: return 59 * 60 * 1000;
5576     case Hour24Section: case Hour12Section: return 59 * 60 * 60 * 1000;
5577 
5578         // Date. unit is day
5579     case DayOfWeekSection: return 7;
5580     case DaySection: return 30;
5581     case MonthSection: return 365 - 31;
5582     case YearSection: return 9999 * 365;
5583     case YearSection2Digits: return 100 * 365;
5584     default:
5585         qWarning("QDateTimeParser::maxChange() Internal error (%s)",
5586                  qPrintable(sectionName(sectionType(index))));
5587     }
5588 
5589     return -1;
5590 }
5591 
fieldInfo(int index) const5592 QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
5593 {
5594     FieldInfo ret = 0;
5595     const SectionNode &sn = sectionNode(index);
5596     const Section s = sn.type;
5597     switch (s) {
5598     case MSecSection:
5599         ret |= Fraction;
5600         // fallthrough
5601     case SecondSection:
5602     case MinuteSection:
5603     case Hour24Section:
5604     case Hour12Section:
5605     case YearSection:
5606     case YearSection2Digits:
5607         ret |= Numeric;
5608         if (s != YearSection) {
5609             ret |= AllowPartial;
5610         }
5611         if (sn.count != 1) {
5612             ret |= FixedWidth;
5613         }
5614         break;
5615     case MonthSection:
5616     case DaySection:
5617         switch (sn.count) {
5618         case 2:
5619             ret |= FixedWidth;
5620             // fallthrough
5621         case 1:
5622             ret |= (Numeric|AllowPartial);
5623             break;
5624         }
5625         break;
5626     case DayOfWeekSection:
5627         if (sn.count == 3)
5628             ret |= FixedWidth;
5629         break;
5630     case AmPmSection:
5631         ret |= FixedWidth;
5632         break;
5633     default:
5634         qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)",
5635                  index, qPrintable(sectionName(sn.type)), sn.count);
5636         break;
5637     }
5638     return ret;
5639 }
5640 
5641 /*!
5642   \internal Get a number that str can become which is between min
5643   and max or -1 if this is not possible.
5644 */
5645 
5646 
sectionFormat(int index) const5647 QString QDateTimeParser::sectionFormat(int index) const
5648 {
5649     const SectionNode &sn = sectionNode(index);
5650     return sectionFormat(sn.type, sn.count);
5651 }
5652 
sectionFormat(Section s,int count) const5653 QString QDateTimeParser::sectionFormat(Section s, int count) const
5654 {
5655     QChar fillChar;
5656     switch (s) {
5657     case AmPmSection: return count == 1 ? QLatin1String("AP") : QLatin1String("ap");
5658     case MSecSection: fillChar = QLatin1Char('z'); break;
5659     case SecondSection: fillChar = QLatin1Char('s'); break;
5660     case MinuteSection: fillChar = QLatin1Char('m'); break;
5661     case Hour24Section: fillChar = QLatin1Char('H'); break;
5662     case Hour12Section: fillChar = QLatin1Char('h'); break;
5663     case DayOfWeekSection:
5664     case DaySection: fillChar = QLatin1Char('d'); break;
5665     case MonthSection: fillChar = QLatin1Char('M'); break;
5666     case YearSection2Digits:
5667     case YearSection: fillChar = QLatin1Char('y'); break;
5668     default:
5669         qWarning("QDateTimeParser::sectionFormat Internal error (%s)",
5670                  qPrintable(sectionName(s)));
5671         return QString();
5672     }
5673     if (fillChar.isNull()) {
5674         qWarning("QDateTimeParser::sectionFormat Internal error 2");
5675         return QString();
5676     }
5677 
5678     QString str;
5679     str.fill(fillChar, count);
5680     return str;
5681 }
5682 
5683 
5684 /*! \internal Returns true if str can be modified to represent a
5685   number that is within min and max.
5686 */
5687 
potentialValue(const QString & str,int min,int max,int index,const QDateTime & currentValue,int insert) const5688 bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index,
5689                                      const QDateTime &currentValue, int insert) const
5690 {
5691     if (str.isEmpty()) {
5692         return true;
5693     }
5694     const int size = sectionMaxSize(index);
5695     int val = (int)locale().toUInt(str);
5696     const SectionNode &sn = sectionNode(index);
5697     if (sn.type == YearSection2Digits) {
5698         val += currentValue.date().year() - (currentValue.date().year() % 100);
5699     }
5700     if (val >= min && val <= max && str.size() == size) {
5701         return true;
5702     } else if (val > max) {
5703         return false;
5704     } else if (str.size() == size && val < min) {
5705         return false;
5706     }
5707 
5708     const int len = size - str.size();
5709     for (int i=0; i<len; ++i) {
5710         for (int j=0; j<10; ++j) {
5711             if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) {
5712                 return true;
5713             } else if (insert >= 0) {
5714                 QString tmp = str;
5715                 tmp.insert(insert, QLatin1Char('0' + j));
5716                 if (potentialValue(tmp, min, max, index, currentValue, insert))
5717                     return true;
5718             }
5719         }
5720     }
5721 
5722     return false;
5723 }
5724 
skipToNextSection(int index,const QDateTime & current,const QString & text) const5725 bool QDateTimeParser::skipToNextSection(int index, const QDateTime &current, const QString &text) const
5726 {
5727     Q_ASSERT(current >= getMinimum() && current <= getMaximum());
5728 
5729     const SectionNode &node = sectionNode(index);
5730     Q_ASSERT(text.size() < sectionMaxSize(index));
5731 
5732     const QDateTime maximum = getMaximum();
5733     const QDateTime minimum = getMinimum();
5734     QDateTime tmp = current;
5735     int min = absoluteMin(index);
5736     setDigit(tmp, index, min);
5737     if (tmp < minimum) {
5738         min = getDigit(minimum, index);
5739     }
5740 
5741     int max = absoluteMax(index, current);
5742     setDigit(tmp, index, max);
5743     if (tmp > maximum) {
5744         max = getDigit(maximum, index);
5745     }
5746     int pos = cursorPosition() - node.pos;
5747     if (pos < 0 || pos >= text.size())
5748         pos = -1;
5749 
5750     const bool potential = potentialValue(text, min, max, index, current, pos);
5751     return !potential;
5752 
5753     /* If the value potentially can become another valid entry we
5754      * don't want to skip to the next. E.g. In a M field (month
5755      * without leading 0 if you type 1 we don't want to autoskip but
5756      * if you type 3 we do
5757     */
5758 }
5759 
5760 /*!
5761   \internal
5762   For debugging. Returns the name of the section \a s.
5763 */
5764 
sectionName(int s) const5765 QString QDateTimeParser::sectionName(int s) const
5766 {
5767     switch (s) {
5768     case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection");
5769     case QDateTimeParser::DaySection: return QLatin1String("DaySection");
5770     case QDateTimeParser::DayOfWeekSection: return QLatin1String("DayOfWeekSection");
5771     case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section");
5772     case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section");
5773     case QDateTimeParser::MSecSection: return QLatin1String("MSecSection");
5774     case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection");
5775     case QDateTimeParser::MonthSection: return QLatin1String("MonthSection");
5776     case QDateTimeParser::SecondSection: return QLatin1String("SecondSection");
5777     case QDateTimeParser::YearSection: return QLatin1String("YearSection");
5778     case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits");
5779     case QDateTimeParser::NoSection: return QLatin1String("NoSection");
5780     case QDateTimeParser::FirstSection: return QLatin1String("FirstSection");
5781     case QDateTimeParser::LastSection: return QLatin1String("LastSection");
5782     default: return QLatin1String("Unknown section ") + QString::number(s);
5783     }
5784 }
5785 
5786 /*!
5787   \internal
5788   For debugging. Returns the name of the state \a s.
5789 */
5790 
stateName(int s) const5791 QString QDateTimeParser::stateName(int s) const
5792 {
5793     switch (s) {
5794     case Invalid: return QLatin1String("Invalid");
5795     case Intermediate: return QLatin1String("Intermediate");
5796     case Acceptable: return QLatin1String("Acceptable");
5797     default: return QLatin1String("Unknown state ") + QString::number(s);
5798     }
5799 }
5800 
5801 #ifndef QT_NO_DATESTRING
fromString(const QString & t,QDate * date,QTime * time) const5802 bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
5803 {
5804     QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN);
5805     QString text = t;
5806     int copy = -1;
5807     const StateNode tmp = parse(text, copy, val, false);
5808     if (tmp.state != Acceptable || tmp.conflicts) {
5809         return false;
5810     }
5811     if (time) {
5812         const QTime t = tmp.value.time();
5813         if (!t.isValid()) {
5814             return false;
5815         }
5816         *time = t;
5817     }
5818 
5819     if (date) {
5820         const QDate d = tmp.value.date();
5821         if (!d.isValid()) {
5822             return false;
5823         }
5824         *date = d;
5825     }
5826     return true;
5827 }
5828 #endif // QT_NO_DATESTRING
5829 
getMinimum() const5830 QDateTime QDateTimeParser::getMinimum() const
5831 {
5832     return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec);
5833 }
5834 
getMaximum() const5835 QDateTime QDateTimeParser::getMaximum() const
5836 {
5837     return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec);
5838 }
5839 
getAmPmText(AmPm ap,Case cs) const5840 QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
5841 {
5842     if (ap == AmText) {
5843         return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am"));
5844     } else {
5845         return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm"));
5846     }
5847 }
5848 
5849 /*
5850   \internal
5851 
5852   I give arg2 preference because arg1 is always a QDateTime.
5853 */
5854 
operator ==(const QDateTimeParser::SectionNode & s1,const QDateTimeParser::SectionNode & s2)5855 bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2)
5856 {
5857     return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count);
5858 }
5859 
5860 #ifdef Q_OS_SYMBIAN
5861 const static TTime UnixEpochOffset(I64LIT(0xdcddb30f2f8000));
5862 const static TInt64 MinimumMillisecondTime(KMinTInt64 / 1000);
5863 const static TInt64 MaximumMillisecondTime(KMaxTInt64 / 1000);
qt_symbian_TTime_To_QDateTime(const TTime & time)5864 QDateTime qt_symbian_TTime_To_QDateTime(const TTime& time)
5865 {
5866     TTimeIntervalMicroSeconds absolute = time.MicroSecondsFrom(UnixEpochOffset);
5867 
5868     return QDateTime::fromMSecsSinceEpoch(absolute.Int64() / 1000);
5869 }
5870 
qt_symbian_QDateTime_To_TTime(const QDateTime & datetime)5871 TTime qt_symbian_QDateTime_To_TTime(const QDateTime& datetime)
5872 {
5873     qint64 absolute = datetime.toMSecsSinceEpoch();
5874     if(absolute > MaximumMillisecondTime)
5875         return TTime(KMaxTInt64);
5876     if(absolute < MinimumMillisecondTime)
5877         return TTime(KMinTInt64);
5878     return TTime(absolute * 1000);
5879 }
5880 
qt_symbian_TTime_To_time_t(const TTime & time)5881 time_t qt_symbian_TTime_To_time_t(const TTime& time)
5882 {
5883     TTimeIntervalSeconds interval;
5884     TInt err = time.SecondsFrom(UnixEpochOffset, interval);
5885     if (err || interval.Int() < 0)
5886         return (time_t) 0;
5887     return (time_t) interval.Int();
5888 }
5889 
qt_symbian_time_t_To_TTime(time_t time)5890 TTime qt_symbian_time_t_To_TTime(time_t time)
5891 {
5892     return UnixEpochOffset + TTimeIntervalSeconds(time);
5893 }
5894 #endif //Q_OS_SYMBIAN
5895 
5896 #endif // QT_BOOTSTRAPPED
5897 
5898 QT_END_NAMESPACE
5899