1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qplatformdefs.h"
43 #include "private/qdatetime_p.h"
45 #include "qdatastream.h"
48 #include "qdatetime.h"
58 # include <qt_windows.h>
60 # include "qfunctions_wince.h"
64 //#define QDATETIMEPARSER_DEBUG
65 #if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM)
66 # define QDTPDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__)
67 # define QDTPDEBUGN qDebug
69 # define QDTPDEBUG if (false) qDebug()
70 # define QDTPDEBUGN if (false) qDebug
74 #include <private/qcore_mac_p.h>
81 MSECS_PER_DAY = 86400000,
83 MSECS_PER_HOUR = 3600000,
85 MSECS_PER_MIN = 60000,
86 JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromDate(1970, 1, 1)
89 static inline QDate fixedDate(int y, int m, int d)
91 QDate result(y, m, 1);
92 result.setDate(y, m, qMin(d, result.daysInMonth()));
96 static inline qint64 julianDayFromDate(qint64 year, int month, int day)
99 // Algorithm from Henry F. Fliegel and Thomas C. Van Flandern
104 return (1461 * (year + 4800 + (month - 14) / 12)) / 4
105 + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12
106 - (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4
110 static void getDateFromJulianDay(qint64 julianDay, int *year, int *month, int *day)
114 // Gregorian calendar
115 // This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern
116 qint64 ell, n, i, j; //TODO These will need to be bigger to prevent overflow!!!
117 ell = julianDay + 68569;
118 n = (4 * ell) / 146097;
119 ell = ell - (146097 * n + 3) / 4;
120 i = (4000 * (ell + 1)) / 1461001;
121 ell = ell - (1461 * i) / 4 + 31;
122 j = (80 * ell) / 2447;
123 d = ell - (2447 * j) / 80;
125 m = j + 2 - (12 * ell);
126 y = 100 * (n - 49) + i + ell;
140 static const char monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
142 #ifndef QT_NO_TEXTDATE
143 static const char * const qt_shortMonthNames[] = {
144 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
145 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
147 #ifndef QT_NO_DATESTRING
148 static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0);
151 /*****************************************************************************
152 QDate member functions
153 *****************************************************************************/
158 \enum QDate::MonthNameType
160 This enum describes the types of the string representation used
163 \value DateFormat This type of name can be used for date-to-string formatting.
164 \value StandaloneFormat This type is used when you need to enumerate months or weekdays.
165 Usually standalone names are represented in singular forms with
166 capitalized first letter.
173 \brief The QDate class provides date functions.
176 A QDate object contains a calendar date, i.e. year, month, and day
177 numbers, in the Gregorian calendar. It can read the current date
178 from the system clock. It provides functions for comparing dates,
179 and for manipulating dates. For example, it is possible to add
180 and subtract days, months, and years to dates.
182 A QDate object is typically created either by giving the year,
183 month, and day numbers explicitly. Note that QDate interprets two
184 digit years as is, i.e., years 0 - 99. A QDate can also be
185 constructed with the static function currentDate(), which creates
186 a QDate object containing the system clock's date. An explicit
187 date can also be set using setDate(). The fromString() function
188 returns a QDate given a string and a date format which is used to
189 interpret the date within the string.
191 The year(), month(), and day() functions provide access to the
192 year, month, and day numbers. Also, dayOfWeek() and dayOfYear()
193 functions are provided. The same information is provided in
194 textual format by the toString(), shortDayName(), longDayName(),
195 shortMonthName(), and longMonthName() functions.
197 QDate provides a full set of operators to compare two QDate
198 objects where smaller means earlier, and larger means later.
200 You can increment (or decrement) a date by a given number of days
201 using addDays(). Similarly you can use addMonths() and addYears().
202 The daysTo() function returns the number of days between two
205 The daysInMonth() and daysInYear() functions return how many days
206 there are in this date's month and year, respectively. The
207 isLeapYear() function indicates whether a date is in a leap year.
213 There is no year 0. Dates in that year are considered invalid. The
214 year -1 is the year "1 before Christ" or "1 before current era."
215 The day before 1 January 1 CE is 31 December 1 BCE.
217 \section2 Range of Valid Dates
219 Dates are stored internally as a Julian Day number, an integer count of
220 every day in a contiguous range, with 24 November 4714 BCE in the Gregorian
221 calendar being Julian Day 0 (1 January 4713 BCE in the Julian calendar).
222 As well as being an efficient and accurate way of storing an absolute date,
223 it is suitable for converting a Date into other calendar systems such as
224 Hebrew, Islamic or Chinese. The Julian Day number can be obtained using
225 QDate::toJulianDay() and can be set using QDate::fromJulianDay().
227 The range of dates able to be stored by QDate as a Julian Day number is
228 limited for convenience from std::numeric_limits<qint64>::min() / 2 to
229 std::numeric_limits<qint64>::max() / 2, which on most platforms means
230 from around 2.5 quadrillion BCE to around 2.5 quadrillion CE, effectively
231 covering the full range of astronomical time. The range of Julian Days
232 able to be accurately converted to and from valid YMD form Dates is
233 restricted to 1 January 4800 BCE to 31 December 1400000 CE due to
234 shortcomings in the available conversion formulas. Conversions outside this
235 range are not guaranteed to be correct. This may change in the future.
237 \sa QTime, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget
243 Constructs a null date. Null dates are invalid.
245 \sa isNull(), isValid()
249 Constructs a date with year \a y, month \a m and day \a d.
251 If the specified date is invalid, the date is not set and
252 isValid() returns false.
254 \warning Years 0 to 99 are interpreted as is, i.e., years
260 QDate::QDate(int y, int m, int d)
267 \fn bool QDate::isNull() const
269 Returns true if the date is null; otherwise returns false. A null
272 \note The behavior of this function is equivalent to isValid().
279 \fn bool QDate::isValid() const
281 Returns true if this date is valid; otherwise returns false.
288 Returns the year of this date. Negative numbers indicate years
289 before 1 CE, such that year -44 is 44 BCE.
291 Returns 0 if the date is invalid.
296 int QDate::year() const
302 getDateFromJulianDay(jd, &y, 0, 0);
307 Returns the number corresponding to the month of this date, using
308 the following convention:
325 Returns 0 if the date is invalid.
330 int QDate::month() const
336 getDateFromJulianDay(jd, 0, &m, 0);
341 Returns the day of the month (1 to 31) of this date.
343 Returns 0 if the date is invalid.
345 \sa year(), month(), dayOfWeek()
348 int QDate::day() const
354 getDateFromJulianDay(jd, 0, 0, &d);
359 Returns the weekday (1 = Monday to 7 = Sunday) for this date.
361 Returns 0 if the date is invalid.
363 \sa day(), dayOfYear(), Qt::DayOfWeek
366 int QDate::dayOfWeek() const
374 return ((jd + 1) % 7) + 7;
378 Returns the day of the year (1 to 365 or 366 on leap years) for
381 Returns 0 if the date is invalid.
383 \sa day(), dayOfWeek()
386 int QDate::dayOfYear() const
391 return jd - julianDayFromDate(year(), 1, 1) + 1;
395 Returns the number of days in the month (28 to 31) for this date.
397 Returns 0 if the date is invalid.
399 \sa day(), daysInYear()
402 int QDate::daysInMonth() const
408 getDateFromJulianDay(jd, &y, &m, 0);
409 if (m == 2 && isLeapYear(y))
411 else if (m < 1 || m > 12)
418 Returns the number of days in the year (365 or 366) for this date.
420 Returns 0 if the date is invalid.
422 \sa day(), daysInMonth()
425 int QDate::daysInYear() const
431 getDateFromJulianDay(jd, &y, 0, 0);
432 return isLeapYear(y) ? 366 : 365;
436 Returns the week number (1 to 53), and stores the year in
437 *\a{yearNumber} unless \a yearNumber is null (the default).
439 Returns 0 if the date is invalid.
441 In accordance with ISO 8601, weeks start on Monday and the first
442 Thursday of a year is always in week 1 of that year. Most years
443 have 52 weeks, but some have 53.
445 *\a{yearNumber} is not always the same as year(). For example, 1
446 January 2000 has week number 52 in the year 1999, and 31 December
447 2002 has week number 1 in the year 2003.
450 Copyright (c) 1989 The Regents of the University of California.
453 Redistribution and use in source and binary forms are permitted
454 provided that the above copyright notice and this paragraph are
455 duplicated in all such forms and that any documentation,
456 advertising materials, and other materials related to such
457 distribution and use acknowledge that the software was developed
458 by the University of California, Berkeley. The name of the
459 University may not be used to endorse or promote products derived
460 from this software without specific prior written permission.
461 THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
462 IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
463 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
468 int QDate::weekNumber(int *yearNumber) const
473 int year = QDate::year();
474 int yday = dayOfYear() - 1;
475 int wday = dayOfWeek();
485 len = isLeapYear(year) ? 366 : 365;
487 ** What yday (-3 ... 3) does
488 ** the ISO year begin on?
490 bot = ((yday + 11 - wday) % 7) - 3;
492 ** What yday does the NEXT
493 ** ISO year begin on?
495 top = bot - (len % 7);
505 w = 1 + ((yday - bot) / 7);
509 yday += isLeapYear(year) ? 366 : 365;
516 #ifndef QT_NO_TEXTDATE
520 Returns the short name of the \a month for the representation specified
523 The months are enumerated using the following convention:
540 The month names will be localized according to the system's locale
543 Returns an empty string if the date is invalid.
545 \sa toString(), longMonthName(), shortDayName(), longDayName()
548 QString QDate::shortMonthName(int month, QDate::MonthNameType type)
550 if (month < 1 || month > 12)
554 case QDate::DateFormat:
555 return QLocale::system().monthName(month, QLocale::ShortFormat);
556 case QDate::StandaloneFormat:
557 return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat);
567 Returns the long name of the \a month for the representation specified
570 The months are enumerated using the following convention:
587 The month names will be localized according to the system's locale
590 Returns an empty string if the date is invalid.
592 \sa toString(), shortMonthName(), shortDayName(), longDayName()
595 QString QDate::longMonthName(int month, MonthNameType type)
597 if (month < 1 || month > 12)
601 case QDate::DateFormat:
602 return QLocale::system().monthName(month, QLocale::LongFormat);
603 case QDate::StandaloneFormat:
604 return QLocale::system().standaloneMonthName(month, QLocale::LongFormat);
614 Returns the short name of the \a weekday for the representation specified
617 The days are enumerated using the following convention:
629 The day names will be localized according to the system's locale
632 Returns an empty string if the date is invalid.
634 \sa toString(), shortMonthName(), longMonthName(), longDayName()
637 QString QDate::shortDayName(int weekday, MonthNameType type)
639 if (weekday < 1 || weekday > 7)
643 case QDate::DateFormat:
644 return QLocale::system().dayName(weekday, QLocale::ShortFormat);
645 case QDate::StandaloneFormat:
646 return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat);
656 Returns the long name of the \a weekday for the representation specified
659 The days are enumerated using the following convention:
671 The day names will be localized according to the system's locale
674 Returns an empty string if the date is invalid.
676 \sa toString(), shortDayName(), shortMonthName(), longMonthName()
679 QString QDate::longDayName(int weekday, MonthNameType type)
681 if (weekday < 1 || weekday > 7)
685 case QDate::DateFormat:
686 return QLocale::system().dayName(weekday, QLocale::LongFormat);
687 case QDate::StandaloneFormat:
688 return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat);
692 return QLocale::system().dayName(weekday, QLocale::LongFormat);
694 #endif //QT_NO_TEXTDATE
696 #ifndef QT_NO_DATESTRING
699 \fn QString QDate::toString(Qt::DateFormat format) const
703 Returns the date as a string. The \a format parameter determines
704 the format of the string.
706 If the \a format is Qt::TextDate, the string is formatted in
707 the default way. QDate::shortDayName() and QDate::shortMonthName()
708 are used to generate the string, so the day and month names will
709 be localized names. An example of this formatting is
712 If the \a format is Qt::ISODate, the string format corresponds
713 to the ISO 8601 extended specification for representations of
714 dates and times, taking the form YYYY-MM-DD, where YYYY is the
715 year, MM is the month of the year (between 01 and 12), and DD is
716 the day of the month between 01 and 31.
718 If the \a format is Qt::SystemLocaleShortDate or
719 Qt::SystemLocaleLongDate, the string format depends on the locale
720 settings of the system. Identical to calling
721 QLocale::system().toString(date, QLocale::ShortFormat) or
722 QLocale::system().toString(date, QLocale::LongFormat).
724 If the \a format is Qt::DefaultLocaleShortDate or
725 Qt::DefaultLocaleLongDate, the string format depends on the
726 default application locale. This is the locale set with
727 QLocale::setDefault(), or the system locale if no default locale
728 has been set. Identical to calling QLocale().toString(date,
729 QLocale::ShortFormat) or QLocale().toString(date,
730 QLocale::LongFormat).
732 If the date is invalid, an empty string will be returned.
734 \warning The Qt::ISODate format is only valid for years in the
735 range 0 to 9999. This restriction may apply to locale-aware
736 formats as well, depending on the locale settings.
738 \sa shortDayName(), shortMonthName()
740 QString QDate::toString(Qt::DateFormat f) const
745 getDateFromJulianDay(jd, &y, &m, &d);
747 case Qt::SystemLocaleDate:
748 case Qt::SystemLocaleShortDate:
749 case Qt::SystemLocaleLongDate:
750 return QLocale::system().toString(*this, f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
751 : QLocale::ShortFormat);
753 case Qt::DefaultLocaleShortDate:
754 case Qt::DefaultLocaleLongDate:
755 return QLocale().toString(*this, f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
756 : QLocale::ShortFormat);
758 #ifndef QT_NO_TEXTDATE
761 return QString::fromLatin1("%0 %1 %2 %3")
762 .arg(shortDayName(dayOfWeek()))
763 .arg(shortMonthName(m))
770 if (year() < 0 || year() > 9999)
772 QString year(QString::number(y).rightJustified(4, QLatin1Char('0')));
773 QString month(QString::number(m).rightJustified(2, QLatin1Char('0')));
774 QString day(QString::number(d).rightJustified(2, QLatin1Char('0')));
775 return year + QLatin1Char('-') + month + QLatin1Char('-') + day;
781 Returns the date as a string. The \a format parameter determines
782 the format of the result string.
784 These expressions may be used:
787 \header \li Expression \li Output
788 \row \li d \li the day as number without a leading zero (1 to 31)
789 \row \li dd \li the day as number with a leading zero (01 to 31)
791 \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
792 Uses QDate::shortDayName().
794 \li the long localized day name (e.g. 'Monday' to 'Sunday').
795 Uses QDate::longDayName().
796 \row \li M \li the month as number without a leading zero (1 to 12)
797 \row \li MM \li the month as number with a leading zero (01 to 12)
799 \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
800 Uses QDate::shortMonthName().
802 \li the long localized month name (e.g. 'January' to 'December').
803 Uses QDate::longMonthName().
804 \row \li yy \li the year as two digit number (00 to 99)
805 \row \li yyyy \li the year as four digit number. If the year is negative,
806 a minus sign is prepended in addition.
809 All other input characters will be ignored. Any sequence of characters that
810 are enclosed in single quotes will be treated as text and not be used as an
811 expression. Two consecutive single quotes ("''") are replaced by a singlequote
814 Example format strings (assuming that the QDate is the 20 July
818 \header \li Format \li Result
819 \row \li dd.MM.yyyy \li 20.07.1969
820 \row \li ddd MMMM d yy \li Sun July 20 69
821 \row \li 'The day is' dddd \li The day is Sunday
824 If the datetime is invalid, an empty string will be returned.
826 \warning The Qt::ISODate format is only valid for years in the
827 range 0 to 9999. This restriction may apply to locale-aware
828 formats as well, depending on the locale settings.
830 \sa QDateTime::toString(), QTime::toString()
833 QString QDate::toString(const QString& format) const
837 return fmtDateTime(format, 0, this);
839 #endif //QT_NO_DATESTRING
842 \fn bool QDate::setYMD(int y, int m, int d)
844 \deprecated in 5.0, use setDate() instead.
846 Sets the date's year \a y, month \a m, and day \a d.
848 If \a y is in the range 0 to 99, it is interpreted as 1900 to
851 Use setDate() instead.
857 Sets the date's \a year, \a month, and \a day. Returns true if
858 the date is valid; otherwise returns false.
860 If the specified date is invalid, the QDate object is set to be
863 Note that any date before 4800 BCE or after about 1.4 million CE
864 may not be accurately stored.
868 bool QDate::setDate(int year, int month, int day)
870 if (isValid(year, month, day))
871 jd = julianDayFromDate(year, month, day);
881 Extracts the date's year, month, and day, and assigns them to
882 *\a year, *\a month, and *\a day. The pointers may be null.
884 Returns 0 if the date is invalid.
886 Note that any date before 4800 BCE or after about 1.4 million CE
887 may not be accurately stored.
889 \sa year(), month(), day(), isValid()
891 void QDate::getDate(int *year, int *month, int *day)
894 getDateFromJulianDay(jd, year, month, day);
906 Returns a QDate object containing a date \a ndays later than the
907 date of this object (or earlier if \a ndays is negative).
909 Returns a null date if the current date is invalid or the new date is
912 \sa addMonths(), addYears(), daysTo()
915 QDate QDate::addDays(qint64 ndays) const
923 // this is basically "d.jd = jd + ndays" with checks for integer overflow
924 // Due to limits on minJd() and maxJd() we know diff will never overflow
930 if ((quint64)qAbs(ndays) <= diff)
937 Returns a QDate object containing a date \a nmonths later than the
938 date of this object (or earlier if \a nmonths is negative).
940 \note If the ending day/month combination does not exist in the
941 resulting month/year, this function will return a date that is the
944 \sa addDays(), addYears()
947 QDate QDate::addMonths(int nmonths) const
955 getDateFromJulianDay(jd, &y, &m, &d);
958 bool increasing = nmonths > 0;
960 while (nmonths != 0) {
961 if (nmonths < 0 && nmonths + 12 <= 0) {
964 } else if (nmonths < 0) {
971 } else if (nmonths - 12 >= 0) {
974 } else if (m == 12) {
987 // was there a sign change?
988 if ((old_y > 0 && y <= 0) ||
989 (old_y < 0 && y >= 0))
990 // yes, adjust the date by +1 or -1 years
991 y += increasing ? +1 : -1;
993 return fixedDate(y, m, d);
997 Returns a QDate object containing a date \a nyears later than the
998 date of this object (or earlier if \a nyears is negative).
1000 \note If the ending day/month combination does not exist in the
1001 resulting year (i.e., if the date was Feb 29 and the final year is
1002 not a leap year), this function will return a date that is the
1003 latest valid date (that is, Feb 28).
1005 \sa addDays(), addMonths()
1008 QDate QDate::addYears(int nyears) const
1014 getDateFromJulianDay(jd, &y, &m, &d);
1019 // was there a sign change?
1020 if ((old_y > 0 && y <= 0) ||
1021 (old_y < 0 && y >= 0))
1022 // yes, adjust the date by +1 or -1 years
1023 y += nyears > 0 ? +1 : -1;
1025 return fixedDate(y, m, d);
1029 Returns the number of days from this date to \a d (which is
1030 negative if \a d is earlier than this date).
1032 Returns 0 if either date is invalid.
1035 \snippet code/src_corelib_tools_qdatetime.cpp 0
1040 qint64 QDate::daysTo(const QDate &d) const
1042 if (isNull() || d.isNull())
1045 // Due to limits on minJd() and maxJd() we know this will never overflow
1051 \fn bool QDate::operator==(const QDate &d) const
1053 Returns true if this date is equal to \a d; otherwise returns
1059 \fn bool QDate::operator!=(const QDate &d) const
1061 Returns true if this date is different from \a d; otherwise
1066 \fn bool QDate::operator<(const QDate &d) const
1068 Returns true if this date is earlier than \a d; otherwise returns
1073 \fn bool QDate::operator<=(const QDate &d) const
1075 Returns true if this date is earlier than or equal to \a d;
1076 otherwise returns false.
1080 \fn bool QDate::operator>(const QDate &d) const
1082 Returns true if this date is later than \a d; otherwise returns
1087 \fn bool QDate::operator>=(const QDate &d) const
1089 Returns true if this date is later than or equal to \a d;
1090 otherwise returns false.
1094 \fn QDate::currentDate()
1095 Returns the current date, as reported by the system clock.
1097 \sa QTime::currentTime(), QDateTime::currentDateTime()
1100 #ifndef QT_NO_DATESTRING
1102 \fn QDate QDate::fromString(const QString &string, Qt::DateFormat format)
1104 Returns the QDate represented by the \a string, using the
1105 \a format given, or an invalid date if the string cannot be
1108 Note for Qt::TextDate: It is recommended that you use the
1109 English short month names (e.g. "Jan"). Although localized month
1110 names can also be used, they depend on the user's locale settings.
1112 QDate QDate::fromString(const QString& s, Qt::DateFormat f)
1120 int year(s.mid(0, 4).toInt());
1121 int month(s.mid(5, 2).toInt());
1122 int day(s.mid(8, 2).toInt());
1123 if (year && month && day)
1124 return QDate(year, month, day);
1127 case Qt::SystemLocaleDate:
1128 case Qt::SystemLocaleShortDate:
1129 case Qt::SystemLocaleLongDate:
1130 return fromString(s, QLocale::system().dateFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
1131 : QLocale::ShortFormat));
1132 case Qt::LocaleDate:
1133 case Qt::DefaultLocaleShortDate:
1134 case Qt::DefaultLocaleLongDate:
1135 return fromString(s, QLocale().dateFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
1136 : QLocale::ShortFormat));
1138 #ifndef QT_NO_TEXTDATE
1139 case Qt::TextDate: {
1140 QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
1142 if (parts.count() != 4) {
1146 QString monthName = parts.at(1);
1148 // Assume that English monthnames are the default
1149 for (int i = 0; i < 12; ++i) {
1150 if (monthName == QLatin1String(qt_shortMonthNames[i])) {
1155 // If English names can't be found, search the localized ones
1157 for (int i = 1; i <= 12; ++i) {
1158 if (monthName == QDate::shortMonthName(i)) {
1164 if (month < 1 || month > 12) {
1169 int day = parts.at(2).toInt(&ok);
1174 int year = parts.at(3).toInt(&ok);
1179 return QDate(year, month, day);
1189 \fn QDate::fromString(const QString &string, const QString &format)
1191 Returns the QDate represented by the \a string, using the \a
1192 format given, or an invalid date if the string cannot be parsed.
1194 These expressions may be used for the format:
1197 \header \li Expression \li Output
1198 \row \li d \li The day as a number without a leading zero (1 to 31)
1199 \row \li dd \li The day as a number with a leading zero (01 to 31)
1201 \li The abbreviated localized day name (e.g. 'Mon' to 'Sun').
1202 Uses QDate::shortDayName().
1204 \li The long localized day name (e.g. 'Monday' to 'Sunday').
1205 Uses QDate::longDayName().
1206 \row \li M \li The month as a number without a leading zero (1 to 12)
1207 \row \li MM \li The month as a number with a leading zero (01 to 12)
1209 \li The abbreviated localized month name (e.g. 'Jan' to 'Dec').
1210 Uses QDate::shortMonthName().
1212 \li The long localized month name (e.g. 'January' to 'December').
1213 Uses QDate::longMonthName().
1214 \row \li yy \li The year as two digit number (00 to 99)
1215 \row \li yyyy \li The year as four digit number. If the year is negative,
1216 a minus sign is prepended in addition.
1219 All other input characters will be treated as text. Any sequence
1220 of characters that are enclosed in single quotes will also be
1221 treated as text and will not be used as an expression. For example:
1223 \snippet code/src_corelib_tools_qdatetime.cpp 1
1225 If the format is not satisfied, an invalid QDate is returned. The
1226 expressions that don't expect leading zeroes (d, M) will be
1227 greedy. This means that they will use two digits even if this
1228 will put them outside the accepted range of values and leaves too
1229 few digits for other sections. For example, the following format
1230 string could have meant January 30 but the M will grab two
1231 digits, resulting in an invalid date:
1233 \snippet code/src_corelib_tools_qdatetime.cpp 2
1235 For any field that is not represented in the format the following
1239 \header \li Field \li Default value
1240 \row \li Year \li 1900
1241 \row \li Month \li 1
1245 The following examples demonstrate the default values:
1247 \snippet code/src_corelib_tools_qdatetime.cpp 3
1249 \sa QDateTime::fromString(), QTime::fromString(), QDate::toString(),
1250 QDateTime::toString(), QTime::toString()
1253 QDate QDate::fromString(const QString &string, const QString &format)
1256 #ifndef QT_BOOTSTRAPPED
1257 QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
1258 if (dt.parseFormat(format))
1259 dt.fromString(string, &date, 0);
1266 #endif // QT_NO_DATESTRING
1271 Returns true if the specified date (\a year, \a month, and \a
1272 day) is valid; otherwise returns false.
1275 \snippet code/src_corelib_tools_qdatetime.cpp 4
1277 \sa isNull(), setDate()
1280 bool QDate::isValid(int year, int month, int day)
1282 // there is no year 0 in the Gregorian calendar
1286 return (day > 0 && month > 0 && month <= 12) &&
1287 (day <= monthDays[month] || (day == 29 && month == 2 && isLeapYear(year)));
1291 \fn bool QDate::isLeapYear(int year)
1293 Returns true if the specified \a year is a leap year; otherwise
1297 bool QDate::isLeapYear(int y)
1299 // No year 0 in Gregorian calendar, so -1, -5, -9 etc are leap years
1303 return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
1306 /*! \fn static QDate QDate::fromJulianDay(qint64 jd)
1308 Converts the Julian day \a jd to a QDate.
1313 /*! \fn int QDate::toJulianDay() const
1315 Converts the date to a Julian day.
1320 /*****************************************************************************
1321 QTime member functions
1322 *****************************************************************************/
1329 \brief The QTime class provides clock time functions.
1332 A QTime object contains a clock time, i.e. the number of hours,
1333 minutes, seconds, and milliseconds since midnight. It can read the
1334 current time from the system clock and measure a span of elapsed
1335 time. It provides functions for comparing times and for
1336 manipulating a time by adding a number of milliseconds.
1338 QTime uses the 24-hour clock format; it has no concept of AM/PM.
1339 Unlike QDateTime, QTime knows nothing about time zones or
1340 daylight savings time (DST).
1342 A QTime object is typically created either by giving the number
1343 of hours, minutes, seconds, and milliseconds explicitly, or by
1344 using the static function currentTime(), which creates a QTime
1345 object that contains the system's local time. Note that the
1346 accuracy depends on the accuracy of the underlying operating
1347 system; not all systems provide 1-millisecond accuracy.
1349 The hour(), minute(), second(), and msec() functions provide
1350 access to the number of hours, minutes, seconds, and milliseconds
1351 of the time. The same information is provided in textual format by
1352 the toString() function.
1354 QTime provides a full set of operators to compare two QTime
1355 objects. One time is considered smaller than another if it is
1356 earlier than the other.
1358 The time a given number of seconds or milliseconds later than a
1359 given time can be found using the addSecs() or addMSecs()
1360 functions. Correspondingly, the number of seconds or milliseconds
1361 between two times can be found using secsTo() or msecsTo().
1363 QTime can be used to measure a span of elapsed time using the
1364 start(), restart(), and elapsed() functions.
1366 \sa QDate, QDateTime
1372 Constructs a null time object. A null time can be a QTime(0, 0, 0, 0)
1373 (i.e., midnight) object, except that isNull() returns true and isValid()
1376 \sa isNull(), isValid()
1380 Constructs a time with hour \a h, minute \a m, seconds \a s and
1383 \a h must be in the range 0 to 23, \a m and \a s must be in the
1384 range 0 to 59, and \a ms must be in the range 0 to 999.
1389 QTime::QTime(int h, int m, int s, int ms)
1391 setHMS(h, m, s, ms);
1396 \fn bool QTime::isNull() const
1398 Returns true if the time is null (i.e., the QTime object was
1399 constructed using the default constructor); otherwise returns
1400 false. A null time is also an invalid time.
1406 Returns true if the time is valid; otherwise returns false. For example,
1407 the time 23:30:55.746 is valid, but 24:12:30 is invalid.
1412 bool QTime::isValid() const
1414 return mds > NullTime && mds < MSECS_PER_DAY;
1419 Returns the hour part (0 to 23) of the time.
1421 Returns -1 if the time is invalid.
1423 \sa minute(), second(), msec()
1426 int QTime::hour() const
1431 return ds() / MSECS_PER_HOUR;
1435 Returns the minute part (0 to 59) of the time.
1437 Returns -1 if the time is invalid.
1439 \sa hour(), second(), msec()
1442 int QTime::minute() const
1447 return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
1451 Returns the second part (0 to 59) of the time.
1453 Returns -1 if the time is invalid.
1455 \sa hour(), minute(), msec()
1458 int QTime::second() const
1463 return (ds() / 1000)%SECS_PER_MIN;
1467 Returns the millisecond part (0 to 999) of the time.
1469 Returns -1 if the time is invalid.
1471 \sa hour(), minute(), second()
1474 int QTime::msec() const
1482 #ifndef QT_NO_DATESTRING
1486 Returns the time as a string. Milliseconds are not included. The
1487 \a format parameter determines the format of the string.
1489 If \a format is Qt::TextDate, the string format is HH:MM:SS; e.g. 1
1490 second before midnight would be "23:59:59".
1492 If \a format is Qt::ISODate, the string format corresponds to the
1493 ISO 8601 extended specification for representations of dates,
1494 which is also HH:MM:SS. (However, contrary to ISO 8601, dates
1495 before 15 October 1582 are handled as Julian dates, not Gregorian
1496 dates. See \l{QDate G and J} {Use of Gregorian and Julian
1497 Calendars}. This might change in a future version of Qt.)
1499 If the \a format is Qt::SystemLocaleShortDate or
1500 Qt::SystemLocaleLongDate, the string format depends on the locale
1501 settings of the system. Identical to calling
1502 QLocale::system().toString(time, QLocale::ShortFormat) or
1503 QLocale::system().toString(time, QLocale::LongFormat).
1505 If the \a format is Qt::DefaultLocaleShortDate or
1506 Qt::DefaultLocaleLongDate, the string format depends on the
1507 default application locale. This is the locale set with
1508 QLocale::setDefault(), or the system locale if no default locale
1509 has been set. Identical to calling QLocale().toString(time,
1510 QLocale::ShortFormat) or QLocale().toString(time,
1511 QLocale::LongFormat).
1513 If the time is invalid, an empty string will be returned.
1516 QString QTime::toString(Qt::DateFormat format) const
1522 case Qt::SystemLocaleDate:
1523 case Qt::SystemLocaleShortDate:
1524 case Qt::SystemLocaleLongDate:
1525 return QLocale::system().toString(*this, format == Qt::SystemLocaleLongDate ? QLocale::LongFormat
1526 : QLocale::ShortFormat);
1527 case Qt::LocaleDate:
1528 case Qt::DefaultLocaleShortDate:
1529 case Qt::DefaultLocaleLongDate:
1530 return QLocale().toString(*this, format == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
1531 : QLocale::ShortFormat);
1536 return QString::fromLatin1("%1:%2:%3")
1537 .arg(hour(), 2, 10, QLatin1Char('0'))
1538 .arg(minute(), 2, 10, QLatin1Char('0'))
1539 .arg(second(), 2, 10, QLatin1Char('0'));
1544 Returns the time as a string. The \a format parameter determines
1545 the format of the result string.
1547 These expressions may be used:
1550 \header \li Expression \li Output
1552 \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
1554 \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
1556 \li the hour without a leading zero (0 to 23, even with AM/PM display)
1558 \li the hour with a leading zero (00 to 23, even with AM/PM display)
1559 \row \li m \li the minute without a leading zero (0 to 59)
1560 \row \li mm \li the minute with a leading zero (00 to 59)
1561 \row \li s \li the second without a leading zero (0 to 59)
1562 \row \li ss \li the second with a leading zero (00 to 59)
1563 \row \li z \li the milliseconds without leading zeroes (0 to 999)
1564 \row \li zzz \li the milliseconds with leading zeroes (000 to 999)
1566 \li use AM/PM display. \e AP will be replaced by either "AM" or "PM".
1568 \li use am/pm display. \e ap will be replaced by either "am" or "pm".
1569 \row \li t \li the timezone (for example "CEST")
1572 All other input characters will be ignored. Any sequence of characters that
1573 are enclosed in single quotes will be treated as text and not be used as an
1574 expression. Two consecutive single quotes ("''") are replaced by a singlequote
1577 Example format strings (assuming that the QTime is 14:13:09.042)
1580 \header \li Format \li Result
1581 \row \li hh:mm:ss.zzz \li 14:13:09.042
1582 \row \li h:m:s ap \li 2:13:9 pm
1583 \row \li H:m:s a \li 14:13:9 pm
1586 If the datetime is invalid, an empty string will be returned.
1587 If \a format is empty, the default format "hh:mm:ss" is used.
1589 \sa QDate::toString(), QDateTime::toString()
1591 QString QTime::toString(const QString& format) const
1593 return fmtDateTime(format, this, 0);
1595 #endif //QT_NO_DATESTRING
1597 Sets the time to hour \a h, minute \a m, seconds \a s and
1600 \a h must be in the range 0 to 23, \a m and \a s must be in the
1601 range 0 to 59, and \a ms must be in the range 0 to 999.
1602 Returns true if the set time is valid; otherwise returns false.
1607 bool QTime::setHMS(int h, int m, int s, int ms)
1609 #if defined(Q_OS_WINCE)
1610 startTick = NullTime;
1612 if (!isValid(h,m,s,ms)) {
1613 mds = NullTime; // make this invalid
1616 mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
1621 Returns a QTime object containing a time \a s seconds later
1622 than the time of this object (or earlier if \a s is negative).
1624 Note that the time will wrap if it passes midnight.
1626 Returns a null time if this time is invalid.
1630 \snippet code/src_corelib_tools_qdatetime.cpp 5
1632 \sa addMSecs(), secsTo(), QDateTime::addSecs()
1635 QTime QTime::addSecs(int s) const
1637 return addMSecs(s * 1000);
1641 Returns the number of seconds from this time to \a t.
1642 If \a t is earlier than this time, the number of seconds returned
1645 Because QTime measures time within a day and there are 86400
1646 seconds in a day, the result is always between -86400 and 86400.
1648 secsTo() does not take into account any milliseconds.
1650 Returns 0 if either time is invalid.
1652 \sa addSecs(), QDateTime::secsTo()
1655 int QTime::secsTo(const QTime &t) const
1657 if (!isValid() || !t.isValid())
1660 // Truncate milliseconds as we do not want to consider them.
1661 int ourSeconds = ds() / 1000;
1662 int theirSeconds = t.ds() / 1000;
1663 return theirSeconds - ourSeconds;
1667 Returns a QTime object containing a time \a ms milliseconds later
1668 than the time of this object (or earlier if \a ms is negative).
1670 Note that the time will wrap if it passes midnight. See addSecs()
1673 Returns a null time if this time is invalid.
1675 \sa addSecs(), msecsTo(), QDateTime::addMSecs()
1678 QTime QTime::addMSecs(int ms) const
1683 // % not well-defined for -ve, but / is.
1684 int negdays = (MSECS_PER_DAY - ms) / MSECS_PER_DAY;
1685 t.mds = (ds() + ms + negdays * MSECS_PER_DAY) % MSECS_PER_DAY;
1687 t.mds = (ds() + ms) % MSECS_PER_DAY;
1690 #if defined(Q_OS_WINCE)
1691 if (startTick > NullTime)
1692 t.startTick = (startTick + ms) % MSECS_PER_DAY;
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
1702 Because QTime measures time within a day and there are 86400
1703 seconds in a day, the result is always between -86400000 and
1706 Returns 0 if either time is invalid.
1708 \sa secsTo(), addMSecs(), QDateTime::msecsTo()
1711 int QTime::msecsTo(const QTime &t) const
1713 if (!isValid() || !t.isValid())
1715 #if defined(Q_OS_WINCE)
1716 // GetLocalTime() for Windows CE has no milliseconds resolution
1717 if (t.startTick > NullTime && startTick > NullTime)
1718 return t.startTick - startTick;
1721 return t.ds() - ds();
1726 \fn bool QTime::operator==(const QTime &t) const
1728 Returns true if this time is equal to \a t; otherwise returns false.
1732 \fn bool QTime::operator!=(const QTime &t) const
1734 Returns true if this time is different from \a t; otherwise returns false.
1738 \fn bool QTime::operator<(const QTime &t) const
1740 Returns true if this time is earlier than \a t; otherwise returns false.
1744 \fn bool QTime::operator<=(const QTime &t) const
1746 Returns true if this time is earlier than or equal to \a t;
1747 otherwise returns false.
1751 \fn bool QTime::operator>(const QTime &t) const
1753 Returns true if this time is later than \a t; otherwise returns false.
1757 \fn bool QTime::operator>=(const QTime &t) const
1759 Returns true if this time is later than or equal to \a t;
1760 otherwise returns false.
1764 \fn QTime::currentTime()
1766 Returns the current time as reported by the system clock.
1768 Note that the accuracy depends on the accuracy of the underlying
1769 operating system; not all systems provide 1-millisecond accuracy.
1772 #ifndef QT_NO_DATESTRING
1774 // These anonymous functions tidy up QDateTime::fromString()
1775 // and avoid confusion of responsibility between it and QTime::fromString().
1777 inline bool isMidnight(int hour, int minute, int second, int msec)
1779 return hour == 24 && minute == 0 && second == 0 && msec == 0;
1782 QTime fromStringImpl(const QString &s, Qt::DateFormat f, bool &isMidnight24)
1785 // Return a null time.
1790 case Qt::SystemLocaleDate:
1791 case Qt::SystemLocaleShortDate:
1792 case Qt::SystemLocaleLongDate:
1794 QLocale::FormatType formatType(Qt::SystemLocaleLongDate ? QLocale::LongFormat : QLocale::ShortFormat);
1795 return QTime::fromString(s, QLocale::system().timeFormat(formatType));
1797 case Qt::LocaleDate:
1798 case Qt::DefaultLocaleShortDate:
1799 case Qt::DefaultLocaleLongDate:
1801 QLocale::FormatType formatType(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat : QLocale::ShortFormat);
1802 return QTime::fromString(s, QLocale().timeFormat(formatType));
1808 const int hour(s.mid(0, 2).toInt(&ok));
1811 const int minute(s.mid(3, 2).toInt(&ok));
1814 if (f == Qt::ISODate) {
1815 if (s.size() == 5) {
1816 // Do not need to specify seconds if using ISO format.
1817 return QTime(hour, minute, 0, 0);
1818 } else if ((s.size() > 6 && s[5] == QLatin1Char(',')) || s[5] == QLatin1Char('.')) {
1819 // Possibly specifying fraction of a minute.
1821 // We only want 5 digits worth of fraction of minute. This follows the existing
1822 // behaviour that determines how milliseconds are read; 4 millisecond digits are
1823 // read and then rounded to 3. If we read at most 5 digits for fraction of minute,
1824 // the maximum amount of millisecond digits it will expand to once converted to
1825 // seconds is 4. E.g. 12:34,99999 will expand to 12:34:59.9994. The milliseconds
1826 // will then be rounded up AND clamped to 999.
1827 const QString minuteFractionStr(QLatin1String("0.") + s.mid(6, 5));
1828 const float minuteFraction = minuteFractionStr.toFloat(&ok);
1831 const float secondWithMs = minuteFraction * 60;
1832 const float second = std::floor(secondWithMs);
1833 const float millisecond = 1000 * (secondWithMs - second);
1834 const int millisecondRounded = qMin(qRound(millisecond), 999);
1836 if (isMidnight(hour, minute, second, millisecondRounded)) {
1837 isMidnight24 = true;
1838 return QTime(0, 0, 0, 0);
1841 return QTime(hour, minute, second, millisecondRounded);
1845 const int second(s.mid(6, 2).toInt(&ok));
1848 const QString msec_s(QLatin1String("0.") + s.mid(9, 4));
1849 const double msec(msec_s.toDouble(&ok));
1851 return QTime(hour, minute, second, 0);
1853 if (f == Qt::ISODate) {
1854 if (isMidnight(hour, minute, second, msec)) {
1855 isMidnight24 = true;
1856 return QTime(0, 0, 0, 0);
1859 return QTime(hour, minute, second, qMin(qRound(msec * 1000.0), 999));
1869 \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format)
1871 Returns the time represented in the \a string as a QTime using the
1872 \a format given, or an invalid time if this is not possible.
1874 Note that fromString() uses a "C" locale encoded string to convert
1875 milliseconds to a float value. If the default locale is not "C",
1876 this may result in two conversion attempts (if the conversion
1877 fails for the default locale). This should be considered an
1878 implementation detail.
1880 QTime QTime::fromString(const QString& s, Qt::DateFormat f)
1883 return fromStringImpl(s, f, unused);
1887 \fn QTime::fromString(const QString &string, const QString &format)
1889 Returns the QTime represented by the \a string, using the \a
1890 format given, or an invalid time if the string cannot be parsed.
1892 These expressions may be used for the format:
1895 \header \li Expression \li Output
1897 \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
1899 \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
1900 \row \li m \li the minute without a leading zero (0 to 59)
1901 \row \li mm \li the minute with a leading zero (00 to 59)
1902 \row \li s \li the second without a leading zero (0 to 59)
1903 \row \li ss \li the second with a leading zero (00 to 59)
1904 \row \li z \li the milliseconds without leading zeroes (0 to 999)
1905 \row \li zzz \li the milliseconds with leading zeroes (000 to 999)
1907 \li interpret as an AM/PM time. \e AP must be either "AM" or "PM".
1909 \li Interpret as an AM/PM time. \e ap must be either "am" or "pm".
1912 All other input characters will be treated as text. Any sequence
1913 of characters that are enclosed in single quotes will also be
1914 treated as text and not be used as an expression.
1916 \snippet code/src_corelib_tools_qdatetime.cpp 6
1918 If the format is not satisfied an invalid QTime is returned.
1919 Expressions that do not expect leading zeroes to be given (h, m, s
1920 and z) are greedy. This means that they will use two digits even if
1921 this puts them outside the range of accepted values and leaves too
1922 few digits for other sections. For example, the following string
1923 could have meant 00:07:10, but the m will grab two digits, resulting
1926 \snippet code/src_corelib_tools_qdatetime.cpp 7
1928 Any field that is not represented in the format will be set to zero.
1931 \snippet code/src_corelib_tools_qdatetime.cpp 8
1933 \sa QDateTime::fromString(), QDate::fromString(), QDate::toString(),
1934 QDateTime::toString(), QTime::toString()
1937 QTime QTime::fromString(const QString &string, const QString &format)
1940 #ifndef QT_BOOTSTRAPPED
1941 QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
1942 if (dt.parseFormat(format))
1943 dt.fromString(string, 0, &time);
1951 #endif // QT_NO_DATESTRING
1957 Returns true if the specified time is valid; otherwise returns
1960 The time is valid if \a h is in the range 0 to 23, \a m and
1961 \a s are in the range 0 to 59, and \a ms is in the range 0 to 999.
1965 \snippet code/src_corelib_tools_qdatetime.cpp 9
1968 bool QTime::isValid(int h, int m, int s, int ms)
1970 return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
1975 Sets this time to the current time. This is practical for timing:
1977 \snippet code/src_corelib_tools_qdatetime.cpp 10
1979 \sa restart(), elapsed(), currentTime()
1984 *this = currentTime();
1988 Sets this time to the current time and returns the number of
1989 milliseconds that have elapsed since the last time start() or
1990 restart() was called.
1992 This function is guaranteed to be atomic and is thus very handy
1993 for repeated measurements. Call start() to start the first
1994 measurement, and restart() for each later measurement.
1996 Note that the counter wraps to zero 24 hours after the last call
1997 to start() or restart().
1999 \warning If the system's clock setting has been changed since the
2000 last time start() or restart() was called, the result is
2001 undefined. This can happen when daylight savings time is turned on
2004 \sa start(), elapsed(), currentTime()
2007 int QTime::restart()
2009 QTime t = currentTime();
2011 if (n < 0) // passed midnight
2018 Returns the number of milliseconds that have elapsed since the
2019 last time start() or restart() was called.
2021 Note that the counter wraps to zero 24 hours after the last call
2022 to start() or restart.
2024 Note that the accuracy depends on the accuracy of the underlying
2025 operating system; not all systems provide 1-millisecond accuracy.
2027 \warning If the system's clock setting has been changed since the
2028 last time start() or restart() was called, the result is
2029 undefined. This can happen when daylight savings time is turned on
2032 \sa start(), restart()
2035 int QTime::elapsed() const
2037 int n = msecsTo(currentTime());
2038 if (n < 0) // passed midnight
2044 /*****************************************************************************
2045 QDateTime member functions
2046 *****************************************************************************/
2052 \brief The QDateTime class provides date and time functions.
2055 A QDateTime object contains a calendar date and a clock time (a
2056 "datetime"). It is a combination of the QDate and QTime classes.
2057 It can read the current datetime from the system clock. It
2058 provides functions for comparing datetimes and for manipulating a
2059 datetime by adding a number of seconds, days, months, or years.
2061 A QDateTime object is typically created either by giving a date
2062 and time explicitly in the constructor, or by using the static
2063 function currentDateTime() that returns a QDateTime object set
2064 to the system clock's time. The date and time can be changed with
2065 setDate() and setTime(). A datetime can also be set using the
2066 setTime_t() function that takes a POSIX-standard "number of
2067 seconds since 00:00:00 on January 1, 1970" value. The fromString()
2068 function returns a QDateTime, given a string and a date format
2069 used to interpret the date within the string.
2071 The date() and time() functions provide access to the date and
2072 time parts of the datetime. The same information is provided in
2073 textual format by the toString() function.
2075 QDateTime provides a full set of operators to compare two
2076 QDateTime objects where smaller means earlier and larger means
2079 You can increment (or decrement) a datetime by a given number of
2080 milliseconds using addMSecs(), seconds using addSecs(), or days
2081 using addDays(). Similarly you can use addMonths() and addYears().
2082 The daysTo() function returns the number of days between two datetimes,
2083 secsTo() returns the number of seconds between two datetimes, and
2084 msecsTo() returns the number of milliseconds between two datetimes.
2086 QDateTime can store datetimes as \l{Qt::LocalTime}{local time} or
2087 as \l{Qt::UTC}{UTC}. QDateTime::currentDateTime() returns a
2088 QDateTime expressed as local time; use toUTC() to convert it to
2089 UTC. You can also use timeSpec() to find out if a QDateTime
2090 object stores a UTC time or a local time. Operations such as
2091 addSecs() and secsTo() are aware of daylight saving time (DST).
2093 \note QDateTime does not account for leap seconds.
2099 There is no year 0. Dates in that year are considered invalid. The
2100 year -1 is the year "1 before Christ" or "1 before current era."
2101 The day before 1 January 1 CE is 31 December 1 BCE.
2103 \section2 Range of Valid Dates
2105 Dates are stored internally as a Julian Day number, an interger count of
2106 every day in a contiguous range, with 24 November 4714 BCE in the Gregorian
2107 calendar being Julian Day 0 (1 January 4713 BCE in the Julian calendar).
2108 As well as being an efficient and accurate way of storing an absolute date,
2109 it is suitable for converting a Date into other calendar systems such as
2110 Hebrew, Islamic or Chinese. The Julian Day number can be obtained using
2111 QDate::toJulianDay() and can be set using QDate::fromJulianDay().
2113 The range of dates able to be stored by QDate as a Julian Day number is
2114 limited for convenience from std::numeric_limits<qint64>::min() / 2 to
2115 std::numeric_limits<qint64>::max() / 2, which on most platforms means
2116 from around 2.5 quadrillion BCE to around 2.5 quadrillion CE, effectively
2117 covering the full range of astronomical time. The range of Julian Days
2118 able to be accurately converted to and from valid YMD form Dates is
2119 restricted to 1 January 4800 BCE to 31 December 1400000 CE due to
2120 shortcomings in the available conversion formulas. Conversions outside this
2121 range are not guaranteed to be correct. This may change in the future.
2124 Use of System Timezone
2126 QDateTime uses the system's time zone information to determine the
2127 offset of local time from UTC. If the system is not configured
2128 correctly or not up-to-date, QDateTime will give wrong results as
2131 \section2 Daylight Savings Time (DST)
2133 QDateTime takes into account the system's time zone information
2134 when dealing with DST. On modern Unix systems, this means it
2135 applies the correct historical DST data whenever possible. On
2136 Windows and Windows CE, where the system doesn't support
2137 historical DST data, historical accuracy is not maintained with
2140 The range of valid dates taking DST into account is 1970-01-01 to
2141 the present, and rules are in place for handling DST correctly
2142 until 2037-12-31, but these could change. For dates falling
2143 outside that range, QDateTime makes a \e{best guess} using the
2144 rules for year 1970 or 2037, but we can't guarantee accuracy. This
2145 means QDateTime doesn't take into account changes in a locale's
2146 time zone before 1970, even if the system's time zone database
2147 supports that information.
2149 \sa QDate, QTime, QDateTimeEdit
2153 Constructs a null datetime (i.e. null date and null time). A null
2154 datetime is invalid, since the date is invalid.
2158 QDateTime::QDateTime()
2159 : d(new QDateTimePrivate)
2165 Constructs a datetime with the given \a date, a valid
2166 time(00:00:00.000), and sets the timeSpec() to Qt::LocalTime.
2169 QDateTime::QDateTime(const QDate &date)
2170 : d(new QDateTimePrivate)
2173 d->time = QTime(0, 0, 0);
2177 Constructs a datetime with the given \a date and \a time, using
2178 the time specification defined by \a spec.
2180 If \a date is valid and \a time is not, the time will be set to midnight.
2183 QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
2184 : d(new QDateTimePrivate)
2187 d->time = date.isValid() && !time.isValid() ? QTime(0, 0, 0) : time;
2188 d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown;
2192 Constructs a copy of the \a other datetime.
2195 QDateTime::QDateTime(const QDateTime &other)
2201 Destroys the datetime.
2203 QDateTime::~QDateTime()
2208 Makes a copy of the \a other datetime and returns a reference to the
2212 QDateTime &QDateTime::operator=(const QDateTime &other)
2218 \fn void QDateTime::swap(QDateTime &other)
2221 Swaps this date-time with \a other. This operation is very fast
2226 Returns true if both the date and the time are null; otherwise
2227 returns false. A null datetime is invalid.
2229 \sa QDate::isNull(), QTime::isNull(), isValid()
2232 bool QDateTime::isNull() const
2234 return d->date.isNull() && d->time.isNull();
2238 Returns true if both the date and the time are valid; otherwise
2241 \sa QDate::isValid(), QTime::isValid()
2244 bool QDateTime::isValid() const
2246 return d->date.isValid() && d->time.isValid();
2250 Returns the date part of the datetime.
2252 \sa setDate(), time(), timeSpec()
2255 QDate QDateTime::date() const
2261 Returns the time part of the datetime.
2263 \sa setTime(), date(), timeSpec()
2266 QTime QDateTime::time() const
2272 Returns the time specification of the datetime.
2274 \sa setTimeSpec(), date(), time(), Qt::TimeSpec
2277 Qt::TimeSpec QDateTime::timeSpec() const
2281 case QDateTimePrivate::UTC:
2283 case QDateTimePrivate::OffsetFromUTC:
2284 return Qt::OffsetFromUTC;
2286 return Qt::LocalTime;
2291 Sets the date part of this datetime to \a date.
2292 If no time is set, it is set to midnight.
2294 \sa date(), setTime(), setTimeSpec()
2297 void QDateTime::setDate(const QDate &date)
2301 if (d->spec == QDateTimePrivate::LocalStandard
2302 || d->spec == QDateTimePrivate::LocalDST)
2303 d->spec = QDateTimePrivate::LocalUnknown;
2304 if (date.isValid() && !d->time.isValid())
2305 d->time = QTime(0, 0, 0);
2309 Sets the time part of this datetime to \a time.
2311 \sa time(), setDate(), setTimeSpec()
2314 void QDateTime::setTime(const QTime &time)
2317 if (d->spec == QDateTimePrivate::LocalStandard
2318 || d->spec == QDateTimePrivate::LocalDST)
2319 d->spec = QDateTimePrivate::LocalUnknown;
2324 Sets the time specification used in this datetime to \a spec.
2325 The datetime will refer to a different point in time.
2328 \snippet code/src_corelib_tools_qdatetime.cpp 19
2330 \sa timeSpec(), setDate(), setTime(), Qt::TimeSpec
2333 void QDateTime::setTimeSpec(Qt::TimeSpec spec)
2340 d->spec = QDateTimePrivate::UTC;
2342 case Qt::OffsetFromUTC:
2343 d->spec = QDateTimePrivate::OffsetFromUTC;
2346 d->spec = QDateTimePrivate::LocalUnknown;
2351 qint64 toMSecsSinceEpoch_helper(qint64 jd, int msecs)
2353 qint64 days = jd - JULIAN_DAY_FOR_EPOCH;
2354 qint64 retval = (days * MSECS_PER_DAY) + msecs;
2361 Returns the datetime as the number of milliseconds that have passed
2362 since 1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
2364 On systems that do not support time zones, this function will
2365 behave as if local time were Qt::UTC.
2367 The behavior for this function is undefined if the datetime stored in
2368 this object is not valid. However, for all valid dates, this function
2369 returns a unique value.
2371 \sa toTime_t(), setMSecsSinceEpoch()
2373 qint64 QDateTime::toMSecsSinceEpoch() const
2377 d->getUTC(utcDate, utcTime);
2379 return toMSecsSinceEpoch_helper(utcDate.toJulianDay(), QTime(0, 0, 0).msecsTo(utcTime));
2383 Returns the datetime as the number of seconds that have passed
2384 since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
2386 On systems that do not support time zones, this function will
2387 behave as if local time were Qt::UTC.
2389 \note This function returns a 32-bit unsigned integer, so it does not
2390 support dates before 1970, but it does support dates after
2391 2038-01-19T03:14:06, which may not be valid time_t values. Be careful
2392 when passing those time_t values to system functions, which could
2393 interpret them as negative dates.
2395 If the date is outside the range 1970-01-01T00:00:00 to
2396 2106-02-07T06:28:14, this function returns -1 cast to an unsigned integer
2399 To get an extended range, use toMSecsSinceEpoch().
2401 \sa toMSecsSinceEpoch(), setTime_t()
2404 uint QDateTime::toTime_t() const
2406 qint64 retval = toMSecsSinceEpoch() / 1000;
2407 if (quint64(retval) >= Q_UINT64_C(0xFFFFFFFF))
2409 return uint(retval);
2415 Sets the date and time given the number of milliseconds,\a msecs, that have
2416 passed since 1970-01-01T00:00:00.000, Coordinated Universal Time
2417 (Qt::UTC). On systems that do not support time zones this function
2418 will behave as if local time were Qt::UTC.
2420 Note that there are possible values for \a msecs that lie outside the
2421 valid range of QDateTime, both negative and positive. The behavior of
2422 this function is undefined for those values.
2424 \sa toMSecsSinceEpoch(), setTime_t()
2426 void QDateTime::setMSecsSinceEpoch(qint64 msecs)
2430 QDateTimePrivate::Spec oldSpec = d->spec;
2432 int ddays = msecs / MSECS_PER_DAY;
2433 msecs %= MSECS_PER_DAY;
2437 msecs += MSECS_PER_DAY;
2440 d->date = QDate(1970, 1, 1).addDays(ddays);
2441 d->time = QTime(0, 0, 0).addMSecs(msecs);
2442 d->spec = QDateTimePrivate::UTC;
2444 if (oldSpec != QDateTimePrivate::UTC)
2445 d->spec = d->getLocal(d->date, d->time);
2449 \fn void QDateTime::setTime_t(uint seconds)
2451 Sets the date and time given the number of \a seconds that have
2452 passed since 1970-01-01T00:00:00, Coordinated Universal Time
2453 (Qt::UTC). On systems that do not support time zones this function
2454 will behave as if local time were Qt::UTC.
2459 void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
2463 QDateTimePrivate::Spec oldSpec = d->spec;
2465 d->date = QDate(1970, 1, 1).addDays(secsSince1Jan1970UTC / SECS_PER_DAY);
2466 d->time = QTime(0, 0, 0).addSecs(secsSince1Jan1970UTC % SECS_PER_DAY);
2467 d->spec = QDateTimePrivate::UTC;
2469 if (oldSpec != QDateTimePrivate::UTC)
2470 d->spec = d->getLocal(d->date, d->time);
2473 #ifndef QT_NO_DATESTRING
2475 \fn QString QDateTime::toString(Qt::DateFormat format) const
2479 Returns the datetime as a string in the \a format given.
2481 If the \a format is Qt::TextDate, the string is formatted in
2482 the default way. QDate::shortDayName(), QDate::shortMonthName(),
2483 and QTime::toString() are used to generate the string, so the
2484 day and month names will be localized names. An example of this
2485 formatting is "Wed May 20 03:40:13 1998".
2487 If the \a format is Qt::ISODate, the string format corresponds
2488 to the ISO 8601 extended specification for representations of
2489 dates and times, taking the form YYYY-MM-DDTHH:MM:SS[Z|[+|-]HH:MM],
2490 depending on the timeSpec() of the QDateTime. If the timeSpec()
2491 is Qt::UTC, Z will be appended to the string; if the timeSpec() is
2492 Qt::OffsetFromUTC the offset in hours and minutes from UTC will
2493 be appended to the string.
2495 If the \a format is Qt::SystemLocaleShortDate or
2496 Qt::SystemLocaleLongDate, the string format depends on the locale
2497 settings of the system. Identical to calling
2498 QLocale::system().toString(datetime, QLocale::ShortFormat) or
2499 QLocale::system().toString(datetime, QLocale::LongFormat).
2501 If the \a format is Qt::DefaultLocaleShortDate or
2502 Qt::DefaultLocaleLongDate, the string format depends on the
2503 default application locale. This is the locale set with
2504 QLocale::setDefault(), or the system locale if no default locale
2505 has been set. Identical to calling QLocale().toString(datetime,
2506 QLocale::ShortFormat) or QLocale().toString(datetime,
2507 QLocale::LongFormat).
2509 If the datetime is invalid, an empty string will be returned.
2511 \warning The Qt::ISODate format is only valid for years in the
2512 range 0 to 9999. This restriction may apply to locale-aware
2513 formats as well, depending on the locale settings.
2515 \sa QDate::toString(), QTime::toString(), Qt::DateFormat
2518 QString QDateTime::toString(Qt::DateFormat f) const
2524 if (f == Qt::ISODate) {
2525 buf = d->date.toString(Qt::ISODate);
2527 return QString(); // failed to convert
2528 buf += QLatin1Char('T');
2529 buf += d->time.toString(Qt::ISODate);
2531 case QDateTimePrivate::UTC:
2532 buf += QLatin1Char('Z');
2534 case QDateTimePrivate::OffsetFromUTC: {
2535 int sign = d->utcOffset >= 0 ? 1: -1;
2536 buf += QString::fromLatin1("%1%2:%3").
2537 arg(sign == 1 ? QLatin1Char('+') : QLatin1Char('-')).
2538 arg(d->utcOffset * sign / SECS_PER_HOUR, 2, 10, QLatin1Char('0')).
2539 arg((d->utcOffset / 60) % 60, 2, 10, QLatin1Char('0'));
2546 #ifndef QT_NO_TEXTDATE
2547 else if (f == Qt::TextDate) {
2549 buf = d->date.shortDayName(d->date.dayOfWeek());
2550 buf += QLatin1Char(' ');
2551 buf += d->date.shortMonthName(d->date.month());
2552 buf += QLatin1Char(' ');
2553 buf += QString::number(d->date.day());
2556 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255);
2557 QString winstr = QString::fromWCharArray(out);
2558 switch (winstr.toInt()) {
2560 buf = d->date.shortDayName(d->date.dayOfWeek());
2561 buf += QLatin1Char(' ');
2562 buf += QString::number(d->date.day());
2563 buf += QLatin1String(". ");
2564 buf += d->date.shortMonthName(d->date.month());
2567 buf = d->date.shortDayName(d->date.dayOfWeek());
2568 buf += QLatin1Char(' ');
2569 buf += d->date.shortMonthName(d->date.month());
2570 buf += QLatin1Char(' ');
2571 buf += QString::number(d->date.day());
2574 buf += QLatin1Char(' ');
2575 buf += d->time.toString();
2576 buf += QLatin1Char(' ');
2577 buf += QString::number(d->date.year());
2581 buf = d->date.toString(f);
2583 return QString(); // failed to convert
2584 buf += QLatin1Char(' ');
2585 buf += d->time.toString(f);
2592 Returns the datetime as a string. The \a format parameter
2593 determines the format of the result string.
2595 These expressions may be used for the date:
2598 \header \li Expression \li Output
2599 \row \li d \li the day as number without a leading zero (1 to 31)
2600 \row \li dd \li the day as number with a leading zero (01 to 31)
2602 \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
2603 Uses QDate::shortDayName().
2605 \li the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
2606 Uses QDate::longDayName().
2607 \row \li M \li the month as number without a leading zero (1-12)
2608 \row \li MM \li the month as number with a leading zero (01-12)
2610 \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
2611 Uses QDate::shortMonthName().
2613 \li the long localized month name (e.g. 'January' to 'December').
2614 Uses QDate::longMonthName().
2615 \row \li yy \li the year as two digit number (00-99)
2616 \row \li yyyy \li the year as four digit number
2619 These expressions may be used for the time:
2622 \header \li Expression \li Output
2624 \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
2626 \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
2627 \row \li m \li the minute without a leading zero (0 to 59)
2628 \row \li mm \li the minute with a leading zero (00 to 59)
2629 \row \li s \li the second without a leading zero (0 to 59)
2630 \row \li ss \li the second with a leading zero (00 to 59)
2631 \row \li z \li the milliseconds without leading zeroes (0 to 999)
2632 \row \li zzz \li the milliseconds with leading zeroes (000 to 999)
2634 \li use AM/PM display. \e AP will be replaced by either "AM" or "PM".
2636 \li use am/pm display. \e ap will be replaced by either "am" or "pm".
2639 All other input characters will be ignored. Any sequence of characters that
2640 are enclosed in single quotes will be treated as text and not be used as an
2641 expression. Two consecutive single quotes ("''") are replaced by a singlequote
2644 Example format strings (assumed that the QDateTime is 21 May 2001
2648 \header \li Format \li Result
2649 \row \li dd.MM.yyyy \li 21.05.2001
2650 \row \li ddd MMMM d yy \li Tue May 21 01
2651 \row \li hh:mm:ss.zzz \li 14:13:09.042
2652 \row \li h:m:s ap \li 2:13:9 pm
2655 If the datetime is invalid, an empty string will be returned.
2657 \sa QDate::toString(), QTime::toString()
2659 QString QDateTime::toString(const QString& format) const
2661 return fmtDateTime(format, &d->time, &d->date);
2663 #endif //QT_NO_DATESTRING
2666 Returns a QDateTime object containing a datetime \a ndays days
2667 later than the datetime of this object (or earlier if \a ndays is
2670 \sa daysTo(), addMonths(), addYears(), addSecs()
2673 QDateTime QDateTime::addDays(qint64 ndays) const
2675 return QDateTime(d->date.addDays(ndays), d->time, timeSpec());
2679 Returns a QDateTime object containing a datetime \a nmonths months
2680 later than the datetime of this object (or earlier if \a nmonths
2683 \sa daysTo(), addDays(), addYears(), addSecs()
2686 QDateTime QDateTime::addMonths(int nmonths) const
2688 return QDateTime(d->date.addMonths(nmonths), d->time, timeSpec());
2692 Returns a QDateTime object containing a datetime \a nyears years
2693 later than the datetime of this object (or earlier if \a nyears is
2696 \sa daysTo(), addDays(), addMonths(), addSecs()
2699 QDateTime QDateTime::addYears(int nyears) const
2701 return QDateTime(d->date.addYears(nyears), d->time, timeSpec());
2704 QDateTime QDateTimePrivate::addMSecs(const QDateTime &dt, qint64 msecs)
2708 dt.d->getUTC(utcDate, utcTime);
2710 addMSecs(utcDate, utcTime, msecs);
2712 return QDateTime(utcDate, utcTime, Qt::UTC).toTimeSpec(dt.timeSpec());
2716 Adds \a msecs to utcDate and \a utcTime as appropriate. It is assumed that
2717 utcDate and utcTime are adjusted to UTC.
2722 void QDateTimePrivate::addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs)
2724 qint64 dd = utcDate.toJulianDay();
2725 int tt = QTime(0, 0, 0).msecsTo(utcTime);
2731 if (msecs >= int(MSECS_PER_DAY)) {
2732 dd += sign * (msecs / MSECS_PER_DAY);
2733 msecs %= MSECS_PER_DAY;
2738 tt = MSECS_PER_DAY - tt - 1;
2739 dd -= tt / MSECS_PER_DAY;
2740 tt = tt % MSECS_PER_DAY;
2741 tt = MSECS_PER_DAY - tt - 1;
2742 } else if (tt >= int(MSECS_PER_DAY)) {
2743 dd += tt / MSECS_PER_DAY;
2744 tt = tt % MSECS_PER_DAY;
2747 utcDate = QDate::fromJulianDay(dd);
2748 utcTime = QTime(0, 0, 0).addMSecs(tt);
2752 Returns a QDateTime object containing a datetime \a s seconds
2753 later than the datetime of this object (or earlier if \a s is
2756 \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears()
2759 QDateTime QDateTime::addSecs(int s) const
2761 return d->addMSecs(*this, qint64(s) * 1000);
2765 Returns a QDateTime object containing a datetime \a msecs miliseconds
2766 later than the datetime of this object (or earlier if \a msecs is
2769 \sa addSecs(), msecsTo(), addDays(), addMonths(), addYears()
2771 QDateTime QDateTime::addMSecs(qint64 msecs) const
2773 return d->addMSecs(*this, msecs);
2777 Returns the number of days from this datetime to the \a other
2778 datetime. The number of days is counted as the number of times
2779 midnight is reached between this datetime to the \a other
2780 datetime. This means that a 10 minute difference from 23:55 to
2781 0:05 the next day counts as one day.
2783 If the \a other datetime is earlier than this datetime,
2784 the value returned is negative.
2787 \snippet code/src_corelib_tools_qdatetime.cpp 15
2789 \sa addDays(), secsTo(), msecsTo()
2792 qint64 QDateTime::daysTo(const QDateTime &other) const
2794 return d->date.daysTo(other.d->date);
2798 Returns the number of seconds from this datetime to the \a other
2799 datetime. If the \a other datetime is earlier than this datetime,
2800 the value returned is negative.
2802 Before performing the comparison, the two datetimes are converted
2803 to Qt::UTC to ensure that the result is correct if one of the two
2804 datetimes has daylight saving time (DST) and the other doesn't.
2806 Returns 0 if either datetime is invalid.
2809 \snippet code/src_corelib_tools_qdatetime.cpp 11
2811 \sa addSecs(), daysTo(), QTime::secsTo()
2814 int QDateTime::secsTo(const QDateTime &other) const
2816 if (!isValid() || !other.isValid())
2822 d->getUTC(date1, time1);
2823 other.d->getUTC(date2, time2);
2825 return (date1.daysTo(date2) * SECS_PER_DAY) + time1.secsTo(time2);
2829 Returns the number of milliseconds from this datetime to the \a other
2830 datetime. If the \a other datetime is earlier than this datetime,
2831 the value returned is negative.
2833 Before performing the comparison, the two datetimes are converted
2834 to Qt::UTC to ensure that the result is correct if one of the two
2835 datetimes has daylight saving time (DST) and the other doesn't.
2837 Returns 0 if either datetime is invalid.
2839 \sa addMSecs(), daysTo(), QTime::msecsTo()
2842 qint64 QDateTime::msecsTo(const QDateTime &other) const
2844 if (!isValid() || !other.isValid())
2852 d->getUTC(selfDate, selfTime);
2853 other.d->getUTC(otherDate, otherTime);
2855 return (static_cast<qint64>(selfDate.daysTo(otherDate)) * static_cast<qint64>(MSECS_PER_DAY))
2856 + static_cast<qint64>(selfTime.msecsTo(otherTime));
2861 \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec specification) const
2863 Returns a copy of this datetime converted to the given time
2867 \snippet code/src_corelib_tools_qdatetime.cpp 16
2869 \sa timeSpec(), toUTC(), toLocalTime()
2872 QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
2874 if ((d->spec == QDateTimePrivate::UTC) == (spec == Qt::UTC))
2878 if (spec == Qt::UTC) {
2879 d->getUTC(ret.d->date, ret.d->time);
2880 ret.d->spec = QDateTimePrivate::UTC;
2882 ret.d->spec = d->getLocal(ret.d->date, ret.d->time);
2888 Returns true if this datetime is equal to the \a other datetime;
2889 otherwise returns false.
2894 bool QDateTime::operator==(const QDateTime &other) const
2896 if (d->spec == other.d->spec && d->utcOffset == other.d->utcOffset)
2897 return d->time == other.d->time && d->date == other.d->date;
2902 d->getUTC(date1, time1);
2903 other.d->getUTC(date2, time2);
2904 return time1 == time2 && date1 == date2;
2909 \fn bool QDateTime::operator!=(const QDateTime &other) const
2911 Returns true if this datetime is different from the \a other
2912 datetime; otherwise returns false.
2914 Two datetimes are different if either the date, the time, or the
2915 time zone components are different.
2921 Returns true if this datetime is earlier than the \a other
2922 datetime; otherwise returns false.
2925 bool QDateTime::operator<(const QDateTime &other) const
2927 if (d->spec == other.d->spec && d->spec != QDateTimePrivate::OffsetFromUTC) {
2928 if (d->date != other.d->date)
2929 return d->date < other.d->date;
2930 return d->time < other.d->time;
2934 d->getUTC(date1, time1);
2935 other.d->getUTC(date2, time2);
2937 return date1 < date2;
2938 return time1 < time2;
2943 \fn bool QDateTime::operator<=(const QDateTime &other) const
2945 Returns true if this datetime is earlier than or equal to the
2946 \a other datetime; otherwise returns false.
2950 \fn bool QDateTime::operator>(const QDateTime &other) const
2952 Returns true if this datetime is later than the \a other datetime;
2953 otherwise returns false.
2957 \fn bool QDateTime::operator>=(const QDateTime &other) const
2959 Returns true if this datetime is later than or equal to the
2960 \a other datetime; otherwise returns false.
2964 \fn QDateTime QDateTime::currentDateTime()
2965 Returns the current datetime, as reported by the system clock, in
2966 the local time zone.
2968 \sa currentDateTimeUtc(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
2972 \fn QDateTime QDateTime::currentDateTimeUtc()
2974 Returns the current datetime, as reported by the system clock, in
2977 \sa currentDateTime(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
2981 \fn qint64 QDateTime::currentMSecsSinceEpoch()
2984 Returns the number of milliseconds since 1970-01-01T00:00:00 Universal
2985 Coordinated Time. This number is like the POSIX time_t variable, but
2986 expressed in milliseconds instead.
2988 \sa currentDateTime(), currentDateTimeUtc(), toTime_t(), toTimeSpec()
2991 static inline uint msecsFromDecomposed(int hour, int minute, int sec, int msec = 0)
2993 return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + 1000 * sec + msec;
2996 #if defined(Q_OS_WIN)
2997 QDate QDate::currentDate()
3001 memset(&st, 0, sizeof(SYSTEMTIME));
3003 d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
3007 QTime QTime::currentTime()
3011 memset(&st, 0, sizeof(SYSTEMTIME));
3013 ct.setHMS(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
3014 #if defined(Q_OS_WINCE)
3015 ct.startTick = GetTickCount() % MSECS_PER_DAY;
3020 QDateTime QDateTime::currentDateTime()
3025 memset(&st, 0, sizeof(SYSTEMTIME));
3027 d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
3028 t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
3029 return QDateTime(d, t);
3032 QDateTime QDateTime::currentDateTimeUtc()
3037 memset(&st, 0, sizeof(SYSTEMTIME));
3039 d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
3040 t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
3041 return QDateTime(d, t, Qt::UTC);
3044 qint64 QDateTime::currentMSecsSinceEpoch() Q_DECL_NOTHROW
3049 memset(&st, 0, sizeof(SYSTEMTIME));
3052 return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
3053 qint64(julianDayFromDate(st.wYear, st.wMonth, st.wDay)
3054 - julianDayFromDate(1970, 1, 1)) * Q_INT64_C(86400000);
3057 #elif defined(Q_OS_UNIX)
3058 QDate QDate::currentDate()
3061 // posix compliant system
3066 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3067 // use the reentrant version of localtime() where available
3070 t = localtime_r(<ime, &res);
3072 t = localtime(<ime);
3073 #endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
3075 d.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
3079 QTime QTime::currentTime()
3082 // posix compliant system
3084 gettimeofday(&tv, 0);
3085 time_t ltime = tv.tv_sec;
3088 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3089 // use the reentrant version of localtime() where available
3092 t = localtime_r(<ime, &res);
3094 t = localtime(<ime);
3098 ct.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
3102 QDateTime QDateTime::currentDateTime()
3104 // posix compliant system
3105 // we have milliseconds
3107 gettimeofday(&tv, 0);
3108 time_t ltime = tv.tv_sec;
3111 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3112 // use the reentrant version of localtime() where available
3115 t = localtime_r(<ime, &res);
3117 t = localtime(<ime);
3121 dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
3123 dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
3124 dt.d->spec = t->tm_isdst > 0 ? QDateTimePrivate::LocalDST :
3125 t->tm_isdst == 0 ? QDateTimePrivate::LocalStandard :
3126 QDateTimePrivate::LocalUnknown;
3130 QDateTime QDateTime::currentDateTimeUtc()
3132 // posix compliant system
3133 // we have milliseconds
3135 gettimeofday(&tv, 0);
3136 time_t ltime = tv.tv_sec;
3139 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3140 // use the reentrant version of localtime() where available
3142 t = gmtime_r(<ime, &res);
3148 dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
3150 dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
3151 dt.d->spec = QDateTimePrivate::UTC;
3155 qint64 QDateTime::currentMSecsSinceEpoch() Q_DECL_NOTHROW
3157 // posix compliant system
3158 // we have milliseconds
3160 gettimeofday(&tv, 0);
3161 return qint64(tv.tv_sec) * Q_INT64_C(1000) + tv.tv_usec / 1000;
3165 #error "What system is this?"
3171 Returns a datetime whose date and time are the number of \a seconds
3172 that have passed since 1970-01-01T00:00:00, Coordinated Universal
3173 Time (Qt::UTC). On systems that do not support time zones, the time
3174 will be set as if local time were Qt::UTC.
3176 \sa toTime_t(), setTime_t()
3178 QDateTime QDateTime::fromTime_t(uint seconds)
3181 d.setTime_t(seconds);
3188 Returns a datetime whose date and time are the number of milliseconds, \a msecs,
3189 that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
3190 Time (Qt::UTC). On systems that do not support time zones, the time
3191 will be set as if local time were Qt::UTC.
3193 Note that there are possible values for \a msecs that lie outside the valid
3194 range of QDateTime, both negative and positive. The behavior of this
3195 function is undefined for those values.
3197 \sa toTime_t(), setTime_t()
3199 QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
3202 d.setMSecsSinceEpoch(msecs);
3210 Sets the offset from UTC to \a seconds, and also sets timeSpec() to
3213 The maximum and minimum offset is 14 positive or negative hours. If
3214 \a seconds is larger or smaller than that, the result is undefined.
3216 0 as offset is identical to UTC. Therefore, if \a seconds is 0, the
3217 timeSpec() will be set to Qt::UTC. Hence the UTC offset always
3218 relates to UTC, and can never relate to local time.
3220 \sa isValid(), utcOffset()
3222 void QDateTime::setUtcOffset(int seconds)
3226 /* The motivation to also setting d->spec is to ensure that the QDateTime
3227 * instance stay in well-defined states all the time, instead of that
3228 * we instruct the user to ensure it. */
3230 d->spec = QDateTimePrivate::UTC;
3232 d->spec = QDateTimePrivate::OffsetFromUTC;
3234 /* Even if seconds is 0 we assign it to utcOffset. */
3235 d->utcOffset = seconds;
3242 Returns the UTC offset in seconds. If the timeSpec() isn't
3243 Qt::OffsetFromUTC, 0 is returned. However, since 0 is a valid UTC
3244 offset the return value of this function cannot be used to determine
3245 whether a utcOffset() is used or is valid, timeSpec() must be
3248 Likewise, if this QDateTime() is invalid or if timeSpec() isn't
3249 Qt::OffsetFromUTC, 0 is returned.
3251 The UTC offset only applies if the timeSpec() is Qt::OffsetFromUTC.
3253 \sa isValid(), setUtcOffset()
3255 int QDateTime::utcOffset() const
3257 if(isValid() && d->spec == QDateTimePrivate::OffsetFromUTC)
3258 return d->utcOffset;
3263 #ifndef QT_NO_DATESTRING
3265 static int fromShortMonthName(const QString &monthName)
3267 // Assume that English monthnames are the default
3268 for (int i = 0; i < 12; ++i) {
3269 if (monthName == QLatin1String(qt_shortMonthNames[i]))
3272 // If English names can't be found, search the localized ones
3273 for (int i = 1; i <= 12; ++i) {
3274 if (monthName == QDate::shortMonthName(i))
3281 \fn QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
3283 Returns the QDateTime represented by the \a string, using the
3284 \a format given, or an invalid datetime if this is not possible.
3286 Note for Qt::TextDate: It is recommended that you use the
3287 English short month names (e.g. "Jan"). Although localized month
3288 names can also be used, they depend on the user's locale settings.
3290 QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
3299 Qt::TimeSpec ts = Qt::LocalTime;
3300 QDate date = QDate::fromString(tmp.left(10), Qt::ISODate);
3301 if (tmp.size() == 10)
3302 return QDateTime(date);
3306 // Recognize UTC specifications
3307 if (tmp.endsWith(QLatin1Char('Z'))) {
3312 // Recognize timezone specifications
3313 QRegExp rx(QLatin1String("[+-]"));
3314 if (tmp.contains(rx)) {
3315 int idx = tmp.indexOf(rx);
3316 QString tmp2 = tmp.mid(idx);
3317 tmp = tmp.left(idx);
3321 if ( tmp2.indexOf(QLatin1Char(':')) == 3 )
3323 const int tzhour(tmp2.mid(ntzhour, 2).toInt(&ok));
3324 const int tzminute(tmp2.mid(ntzminute, 2).toInt(&ok));
3325 QTime tzt(tzhour, tzminute);
3326 int utcOffset = (tzt.hour() * 60 + tzt.minute()) * 60;
3327 if ( utcOffset != 0 ) {
3328 ts = Qt::OffsetFromUTC;
3329 QDateTime dt(date, QTime::fromString(tmp, Qt::ISODate), ts);
3330 dt.setUtcOffset( utcOffset * (tmp2.startsWith(QLatin1Char('-')) ? -1 : 1) );
3335 bool isMidnight24 = false;
3336 // Might be end of day (24:00, including variants), which QTime considers invalid.
3337 QTime time(fromStringImpl(tmp, Qt::ISODate, isMidnight24));
3339 // ISO 8601 (section 4.2.3) says that 24:00 is equivalent to 00:00 the next day.
3340 date = date.addDays(1);
3343 return QDateTime(date, time, ts);
3345 case Qt::SystemLocaleDate:
3346 case Qt::SystemLocaleShortDate:
3347 case Qt::SystemLocaleLongDate:
3348 return fromString(s, QLocale::system().dateTimeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
3349 : QLocale::ShortFormat));
3350 case Qt::LocaleDate:
3351 case Qt::DefaultLocaleShortDate:
3352 case Qt::DefaultLocaleLongDate:
3353 return fromString(s, QLocale().dateTimeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
3354 : QLocale::ShortFormat));
3355 #if !defined(QT_NO_TEXTDATE)
3356 case Qt::TextDate: {
3357 QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
3359 if ((parts.count() < 5) || (parts.count() > 6)) {
3363 // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974"
3364 int month = -1, day = -1;
3367 month = fromShortMonthName(parts.at(1));
3369 day = parts.at(2).toInt(&ok);
3374 if (month == -1 || day == -1) {
3375 // first variant failed, lets try the other
3376 month = fromShortMonthName(parts.at(2));
3378 QString dayStr = parts.at(1);
3379 if (dayStr.endsWith(QLatin1Char('.'))) {
3381 day = dayStr.toInt(&ok);
3390 if (month == -1 || day == -1) {
3391 // both variants failed, give up
3396 QStringList timeParts = parts.at(3).split(QLatin1Char(':'));
3397 if ((timeParts.count() == 3) || (timeParts.count() == 2)) {
3398 year = parts.at(4).toInt(&ok);
3402 timeParts = parts.at(4).split(QLatin1Char(':'));
3403 if ((timeParts.count() != 3) && (timeParts.count() != 2))
3405 year = parts.at(3).toInt(&ok);
3410 int hour = timeParts.at(0).toInt(&ok);
3415 int minute = timeParts.at(1).toInt(&ok);
3420 int second = (timeParts.count() > 2) ? timeParts.at(2).toInt(&ok) : 0;
3425 QDate date(year, month, day);
3426 QTime time(hour, minute, second);
3428 if (parts.count() == 5)
3429 return QDateTime(date, time, Qt::LocalTime);
3431 QString tz = parts.at(5);
3432 if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
3434 QDateTime dt(date, time, Qt::UTC);
3435 if (tz.length() > 3) {
3437 QChar sign = tz.at(3);
3438 if ((sign != QLatin1Char('+'))
3439 && (sign != QLatin1Char('-'))) {
3442 int tzhour = tz.mid(4, 2).toInt(&ok);
3445 int tzminute = tz.mid(6).toInt(&ok);
3448 tzoffset = (tzhour*60 + tzminute) * 60;
3449 if (sign == QLatin1Char('-'))
3450 tzoffset = -tzoffset;
3451 dt.setUtcOffset(tzoffset);
3453 return dt.toLocalTime();
3455 #endif //QT_NO_TEXTDATE
3462 \fn QDateTime::fromString(const QString &string, const QString &format)
3464 Returns the QDateTime represented by the \a string, using the \a
3465 format given, or an invalid datetime if the string cannot be parsed.
3467 These expressions may be used for the date part of the format string:
3470 \header \li Expression \li Output
3471 \row \li d \li the day as number without a leading zero (1 to 31)
3472 \row \li dd \li the day as number with a leading zero (01 to 31)
3474 \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
3475 Uses QDate::shortDayName().
3477 \li the long localized day name (e.g. 'Monday' to 'Sunday').
3478 Uses QDate::longDayName().
3479 \row \li M \li the month as number without a leading zero (1-12)
3480 \row \li MM \li the month as number with a leading zero (01-12)
3482 \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
3483 Uses QDate::shortMonthName().
3485 \li the long localized month name (e.g. 'January' to 'December').
3486 Uses QDate::longMonthName().
3487 \row \li yy \li the year as two digit number (00-99)
3488 \row \li yyyy \li the year as four digit number
3491 \note Unlike the other version of this function, day and month names must
3492 be given in the user's local language. It is only possible to use the English
3493 names if the user's language is English.
3495 These expressions may be used for the time part of the format string:
3498 \header \li Expression \li Output
3500 \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
3502 \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
3504 \li the hour without a leading zero (0 to 23, even with AM/PM display)
3506 \li the hour with a leading zero (00 to 23, even with AM/PM display)
3507 \row \li m \li the minute without a leading zero (0 to 59)
3508 \row \li mm \li the minute with a leading zero (00 to 59)
3509 \row \li s \li the second without a leading zero (0 to 59)
3510 \row \li ss \li the second with a leading zero (00 to 59)
3511 \row \li z \li the milliseconds without leading zeroes (0 to 999)
3512 \row \li zzz \li the milliseconds with leading zeroes (000 to 999)
3514 \li interpret as an AM/PM time. \e AP must be either "AM" or "PM".
3516 \li Interpret as an AM/PM time. \e ap must be either "am" or "pm".
3519 All other input characters will be treated as text. Any sequence
3520 of characters that are enclosed in single quotes will also be
3521 treated as text and not be used as an expression.
3523 \snippet code/src_corelib_tools_qdatetime.cpp 12
3525 If the format is not satisfied an invalid QDateTime is returned.
3526 The expressions that don't have leading zeroes (d, M, h, m, s, z) will be
3527 greedy. This means that they will use two digits even if this will
3528 put them outside the range and/or leave too few digits for other
3531 \snippet code/src_corelib_tools_qdatetime.cpp 13
3533 This could have meant 1 January 00:30.00 but the M will grab
3536 For any field that is not represented in the format the following
3540 \header \li Field \li Default value
3541 \row \li Year \li 1900
3542 \row \li Month \li 1 (January)
3545 \row \li Minute \li 0
3546 \row \li Second \li 0
3551 \snippet code/src_corelib_tools_qdatetime.cpp 14
3553 \sa QDate::fromString(), QTime::fromString(), QDate::toString(),
3554 QDateTime::toString(), QTime::toString()
3557 QDateTime QDateTime::fromString(const QString &string, const QString &format)
3559 #ifndef QT_BOOTSTRAPPED
3563 QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
3564 if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
3565 return QDateTime(date, time);
3570 return QDateTime(QDate(), QTime(-1, -1, -1));
3573 #endif // QT_NO_DATESTRING
3575 \fn QDateTime QDateTime::toLocalTime() const
3577 Returns a datetime containing the date and time information in
3578 this datetime, but specified using the Qt::LocalTime definition.
3582 \snippet code/src_corelib_tools_qdatetime.cpp 17
3588 \fn QDateTime QDateTime::toUTC() const
3590 Returns a datetime containing the date and time information in
3591 this datetime, but specified using the Qt::UTC definition.
3595 \snippet code/src_corelib_tools_qdatetime.cpp 18
3603 void QDateTime::detach()
3608 /*****************************************************************************
3609 Date/time stream functions
3610 *****************************************************************************/
3612 #ifndef QT_NO_DATASTREAM
3616 Writes the \a date to stream \a out.
3618 \sa {Serializing Qt Data Types}
3621 QDataStream &operator<<(QDataStream &out, const QDate &date)
3623 if (out.version() < QDataStream::Qt_5_0)
3624 return out << quint32(date.jd);
3626 return out << qint64(date.jd);
3632 Reads a date from stream \a in into the \a date.
3634 \sa {Serializing Qt Data Types}
3637 QDataStream &operator>>(QDataStream &in, QDate &date)
3639 if (in.version() < QDataStream::Qt_5_0) {
3642 // Older versions consider 0 an invalid jd.
3643 date.jd = (jd != 0 ? jd : QDate::nullJd());
3656 Writes \a time to stream \a out.
3658 \sa {Serializing Qt Data Types}
3661 QDataStream &operator<<(QDataStream &out, const QTime &time)
3663 return out << quint32(time.mds);
3669 Reads a time from stream \a in into the given \a time.
3671 \sa {Serializing Qt Data Types}
3674 QDataStream &operator>>(QDataStream &in, QTime &time)
3685 Writes \a dateTime to the \a out stream.
3687 \sa {Serializing Qt Data Types}
3689 QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
3691 if (out.version() >= 13) {
3692 if (dateTime.isValid()) {
3693 QDateTime asUTC = dateTime.toUTC();
3694 out << asUTC.d->date << asUTC.d->time;
3696 out << dateTime.d->date << dateTime.d->time;
3698 out << (qint8)dateTime.timeSpec();
3700 out << dateTime.d->date << dateTime.d->time;
3701 if (out.version() >= 7)
3702 out << (qint8)dateTime.d->spec;
3710 Reads a datetime from the stream \a in into \a dateTime.
3712 \sa {Serializing Qt Data Types}
3715 QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
3719 in >> dateTime.d->date >> dateTime.d->time;
3721 if (in.version() >= 13) {
3724 if (dateTime.isValid()) {
3725 // We always store the datetime as UTC in 13 onwards.
3726 dateTime.d->spec = QDateTimePrivate::UTC;
3727 dateTime = dateTime.toTimeSpec(static_cast<Qt::TimeSpec>(ts));
3730 qint8 ts = (qint8)QDateTimePrivate::LocalUnknown;
3731 if (in.version() >= 7)
3733 dateTime.d->spec = (QDateTimePrivate::Spec)ts;
3737 #endif // QT_NO_DATASTREAM
3741 // checks if there is an unqoted 'AP' or 'ap' in the string
3742 static bool hasUnquotedAP(const QString &f)
3744 const QLatin1Char quote('\'');
3745 bool inquote = false;
3746 const int max = f.size();
3747 for (int i=0; i<max; ++i) {
3748 if (f.at(i) == quote) {
3750 } else if (!inquote && f.at(i).toUpper() == QLatin1Char('A')) {
3757 #ifndef QT_NO_DATESTRING
3758 /*****************************************************************************
3759 Some static function used by QDate, QTime and QDateTime
3760 *****************************************************************************/
3762 // Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens
3763 static QString getFmtString(const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = false)
3772 if (f.startsWith(QLatin1String("hh")) || f.startsWith(QLatin1String("HH"))) {
3773 const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
3774 if (hour12 && dt->hour() > 12)
3775 buf = QString::number(dt->hour() - 12).rightJustified(2, QLatin1Char('0'), true);
3776 else if (hour12 && dt->hour() == 0)
3777 buf = QLatin1String("12");
3779 buf = QString::number(dt->hour()).rightJustified(2, QLatin1Char('0'), true);
3781 } else if (f.at(0) == QLatin1Char('h') || f.at(0) == QLatin1Char('H')) {
3782 const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
3783 if (hour12 && dt->hour() > 12)
3784 buf = QString::number(dt->hour() - 12);
3785 else if (hour12 && dt->hour() == 0)
3786 buf = QLatin1String("12");
3788 buf = QString::number(dt->hour());
3790 } else if (f.startsWith(QLatin1String("mm"))) {
3791 buf = QString::number(dt->minute()).rightJustified(2, QLatin1Char('0'), true);
3793 } else if (f.at(0) == (QLatin1Char('m'))) {
3794 buf = QString::number(dt->minute());
3796 } else if (f.startsWith(QLatin1String("ss"))) {
3797 buf = QString::number(dt->second()).rightJustified(2, QLatin1Char('0'), true);
3799 } else if (f.at(0) == QLatin1Char('s')) {
3800 buf = QString::number(dt->second());
3801 } else if (f.startsWith(QLatin1String("zzz"))) {
3802 buf = QString::number(dt->msec()).rightJustified(3, QLatin1Char('0'), true);
3804 } else if (f.at(0) == QLatin1Char('z')) {
3805 buf = QString::number(dt->msec());
3807 } else if (f.at(0).toUpper() == QLatin1Char('A')) {
3808 const bool upper = f.at(0) == QLatin1Char('A');
3809 buf = dt->hour() < 12 ? QLatin1String("am") : QLatin1String("pm");
3811 buf = buf.toUpper();
3812 if (f.size() > 1 && f.at(1).toUpper() == QLatin1Char('P') &&
3813 f.at(0).isUpper() == f.at(1).isUpper()) {
3822 if (f.startsWith(QLatin1String("dddd"))) {
3823 buf = dd->longDayName(dd->dayOfWeek());
3825 } else if (f.startsWith(QLatin1String("ddd"))) {
3826 buf = dd->shortDayName(dd->dayOfWeek());
3828 } else if (f.startsWith(QLatin1String("dd"))) {
3829 buf = QString::number(dd->day()).rightJustified(2, QLatin1Char('0'), true);
3831 } else if (f.at(0) == QLatin1Char('d')) {
3832 buf = QString::number(dd->day());
3834 } else if (f.startsWith(QLatin1String("MMMM"))) {
3835 buf = dd->longMonthName(dd->month());
3837 } else if (f.startsWith(QLatin1String("MMM"))) {
3838 buf = dd->shortMonthName(dd->month());
3840 } else if (f.startsWith(QLatin1String("MM"))) {
3841 buf = QString::number(dd->month()).rightJustified(2, QLatin1Char('0'), true);
3843 } else if (f.at(0) == QLatin1Char('M')) {
3844 buf = QString::number(dd->month());
3846 } else if (f.startsWith(QLatin1String("yyyy"))) {
3847 const int year = dd->year();
3848 buf = QString::number(qAbs(year)).rightJustified(4, QLatin1Char('0'));
3853 buf.prepend(QLatin1Char('-'));
3857 } else if (f.startsWith(QLatin1String("yy"))) {
3858 buf = QString::number(dd->year()).right(2).rightJustified(2, QLatin1Char('0'));
3862 if (removed == 0 || removed >= f.size()) {
3866 return buf + getFmtString(f.mid(removed), dt, dd, am_pm);
3869 // Parses the format string and uses getFmtString to get the values for the tokens. Ret
3870 static QString fmtDateTime(const QString& f, const QTime* dt, const QDate* dd)
3876 if (dt && !dt->isValid())
3878 if (dd && !dd->isValid())
3881 const bool ap = hasUnquotedAP(f);
3886 for (int i = 0, n = f.length(); i < n; ++i) {
3887 const QChar c = f.at(i);
3888 const uint cc = c.unicode();
3891 if (i > 0 && f.at(i - 1).unicode() == cc)
3895 if (!frm.isEmpty()) {
3896 buf += getFmtString(frm, dt, dd, ap);
3901 } else if (status == '\'') {
3903 } else if (c == status) {
3904 if (ap && (cc == 'P' || cc == 'p'))
3908 buf += getFmtString(frm, dt, dd, ap);
3910 if (cc == 'h' || cc == 'm' || cc == 'H' || cc == 's' || cc == 'z') {
3913 } else if (cc == 'd' || cc == 'M' || cc == 'y') {
3916 } else if (ap && cc == 'A') {
3919 } else if (ap && cc == 'a') {
3929 buf += getFmtString(frm, dt, dd, ap);
3933 #endif // QT_NO_DATESTRING
3936 static const int LowerYear = 1980;
3938 static const int LowerYear = 1970;
3940 static const int UpperYear = 2037;
3942 static QDate adjustDate(QDate date)
3944 QDate lowerLimit(LowerYear, 1, 2);
3945 QDate upperLimit(UpperYear, 12, 30);
3947 if (date > lowerLimit && date < upperLimit)
3950 int month = date.month();
3951 int day = date.day();
3953 // neither 1970 nor 2037 are leap years, so make sure date isn't Feb 29
3954 if (month == 2 && day == 29)
3957 if (date < lowerLimit)
3958 date.setDate(LowerYear, month, day);
3960 date.setDate(UpperYear, month, day);
3965 static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time)
3967 QDate fakeDate = adjustDate(date);
3969 // won't overflow because of fakeDate
3970 time_t secsSince1Jan1970UTC = toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime(0, 0, 0).msecsTo(time)) / 1000;
3973 #if defined(Q_OS_WINCE)
3975 FILETIME utcTime = time_tToFt(secsSince1Jan1970UTC);
3976 FILETIME resultTime;
3977 FileTimeToLocalFileTime(&utcTime , &resultTime);
3979 FileTimeToSystemTime(&resultTime , &sysTime);
3981 res.tm_sec = sysTime.wSecond;
3982 res.tm_min = sysTime.wMinute;
3983 res.tm_hour = sysTime.wHour;
3984 res.tm_mday = sysTime.wDay;
3985 res.tm_mon = sysTime.wMonth - 1;
3986 res.tm_year = sysTime.wYear - 1900;
3988 #elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3989 // use the reentrant version of localtime() where available
3992 brokenDown = localtime_r(&secsSince1Jan1970UTC, &res);
3993 #elif defined(_MSC_VER) && _MSC_VER >= 1400
3995 if (!_localtime64_s(&res, &secsSince1Jan1970UTC))
3998 brokenDown = localtime(&secsSince1Jan1970UTC);
4001 date = QDate(1970, 1, 1);
4003 return QDateTimePrivate::LocalUnknown;
4005 int deltaDays = fakeDate.daysTo(date);
4006 date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
4007 time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
4008 date = date.addDays(deltaDays);
4009 if (brokenDown->tm_isdst > 0)
4010 return QDateTimePrivate::LocalDST;
4011 else if (brokenDown->tm_isdst < 0)
4012 return QDateTimePrivate::LocalUnknown;
4014 return QDateTimePrivate::LocalStandard;
4018 static void localToUtc(QDate &date, QTime &time, int isdst)
4020 if (!date.isValid())
4023 QDate fakeDate = adjustDate(date);
4026 localTM.tm_sec = time.second();
4027 localTM.tm_min = time.minute();
4028 localTM.tm_hour = time.hour();
4029 localTM.tm_mday = fakeDate.day();
4030 localTM.tm_mon = fakeDate.month() - 1;
4031 localTM.tm_year = fakeDate.year() - 1900;
4032 localTM.tm_isdst = (int)isdst;
4033 #if defined(Q_OS_WINCE)
4034 time_t secsSince1Jan1970UTC = (toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime().msecsTo(time)) / 1000);
4036 #if defined(Q_OS_WIN)
4039 time_t secsSince1Jan1970UTC = mktime(&localTM);
4042 #if defined(Q_OS_WINCE)
4044 FILETIME localTime = time_tToFt(secsSince1Jan1970UTC);
4046 FileTimeToSystemTime(&localTime, &sysTime);
4047 FILETIME resultTime;
4048 LocalFileTimeToFileTime(&localTime , &resultTime);
4049 FileTimeToSystemTime(&resultTime , &sysTime);
4050 res.tm_sec = sysTime.wSecond;
4051 res.tm_min = sysTime.wMinute;
4052 res.tm_hour = sysTime.wHour;
4053 res.tm_mday = sysTime.wDay;
4054 res.tm_mon = sysTime.wMonth - 1;
4055 res.tm_year = sysTime.wYear - 1900;
4056 res.tm_isdst = (int)isdst;
4058 #elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
4059 // use the reentrant version of gmtime() where available
4061 brokenDown = gmtime_r(&secsSince1Jan1970UTC, &res);
4062 #elif defined(_MSC_VER) && _MSC_VER >= 1400
4064 if (!_gmtime64_s(&res, &secsSince1Jan1970UTC))
4067 brokenDown = gmtime(&secsSince1Jan1970UTC);
4068 #endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
4070 date = QDate(1970, 1, 1);
4073 int deltaDays = fakeDate.daysTo(date);
4074 date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
4075 time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
4076 date = date.addDays(deltaDays);
4080 QDateTimePrivate::Spec QDateTimePrivate::getLocal(QDate &outDate, QTime &outTime) const
4084 if (spec == QDateTimePrivate::UTC)
4085 return utcToLocal(outDate, outTime);
4089 void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const
4093 const bool isOffset = spec == QDateTimePrivate::OffsetFromUTC;
4095 if (spec != QDateTimePrivate::UTC && !isOffset)
4096 localToUtc(outDate, outTime, (int)spec);
4099 addMSecs(outDate, outTime, -(qint64(utcOffset) * 1000));
4102 #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
4103 QDebug operator<<(QDebug dbg, const QDate &date)
4105 dbg.nospace() << "QDate(" << date.toString() << ')';
4109 QDebug operator<<(QDebug dbg, const QTime &time)
4111 dbg.nospace() << "QTime(" << time.toString() << ')';
4115 QDebug operator<<(QDebug dbg, const QDateTime &date)
4117 dbg.nospace() << "QDateTime(" << date.toString() << ')';
4122 /*! \fn uint qHash(const QDateTime &key, uint seed = 0)
4126 Returns the hash value for the \a key, using \a seed to seed the calculation.
4128 uint qHash(const QDateTime &key, uint seed)
4130 // Use to toMSecsSinceEpoch instead of individual qHash functions for
4131 // QDate/QTime/spec/offset because QDateTime::operator== converts both arguments
4132 // to the same timezone. If we don't, qHash would return different hashes for
4133 // two QDateTimes that are equivalent once converted to the same timezone.
4134 return qHash(key.toMSecsSinceEpoch(), seed);
4137 /*! \fn uint qHash(const QDate &key, uint seed = 0)
4141 Returns the hash value for the \a key, using \a seed to seed the calculation.
4143 uint qHash(const QDate &key, uint seed) Q_DECL_NOTHROW
4145 return qHash(key.toJulianDay(), seed);
4148 /*! \fn uint qHash(const QTime &key, uint seed = 0)
4152 Returns the hash value for the \a key, using \a seed to seed the calculation.
4154 uint qHash(const QTime &key, uint seed) Q_DECL_NOTHROW
4156 return qHash(QTime(0, 0, 0, 0).msecsTo(key), seed);
4159 #ifndef QT_BOOTSTRAPPED
4163 Gets the digit from a datetime. E.g.
4165 QDateTime var(QDate(2004, 02, 02));
4166 int digit = getDigit(var, Year);
4170 int QDateTimeParser::getDigit(const QDateTime &t, int index) const
4172 if (index < 0 || index >= sectionNodes.size()) {
4173 #ifndef QT_NO_DATESTRING
4174 qWarning("QDateTimeParser::getDigit() Internal error (%s %d)",
4175 qPrintable(t.toString()), index);
4177 qWarning("QDateTimeParser::getDigit() Internal error (%d)", index);
4181 const SectionNode &node = sectionNodes.at(index);
4182 switch (node.type) {
4183 case Hour24Section: case Hour12Section: return t.time().hour();
4184 case MinuteSection: return t.time().minute();
4185 case SecondSection: return t.time().second();
4186 case MSecSection: return t.time().msec();
4187 case YearSection2Digits:
4188 case YearSection: return t.date().year();
4189 case MonthSection: return t.date().month();
4190 case DaySection: return t.date().day();
4191 case DayOfWeekSectionShort:
4192 case DayOfWeekSectionLong: return t.date().day();
4193 case AmPmSection: return t.time().hour() > 11 ? 1 : 0;
4198 #ifndef QT_NO_DATESTRING
4199 qWarning("QDateTimeParser::getDigit() Internal error 2 (%s %d)",
4200 qPrintable(t.toString()), index);
4202 qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index);
4209 Sets a digit in a datetime. E.g.
4211 QDateTime var(QDate(2004, 02, 02));
4212 int digit = getDigit(var, Year);
4214 setDigit(&var, Year, 2005);
4215 digit = getDigit(var, Year);
4219 bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
4221 if (index < 0 || index >= sectionNodes.size()) {
4222 #ifndef QT_NO_DATESTRING
4223 qWarning("QDateTimeParser::setDigit() Internal error (%s %d %d)",
4224 qPrintable(v.toString()), index, newVal);
4226 qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal);
4230 const SectionNode &node = sectionNodes.at(index);
4232 int year, month, day, hour, minute, second, msec;
4233 year = v.date().year();
4234 month = v.date().month();
4235 day = v.date().day();
4236 hour = v.time().hour();
4237 minute = v.time().minute();
4238 second = v.time().second();
4239 msec = v.time().msec();
4241 switch (node.type) {
4242 case Hour24Section: case Hour12Section: hour = newVal; break;
4243 case MinuteSection: minute = newVal; break;
4244 case SecondSection: second = newVal; break;
4245 case MSecSection: msec = newVal; break;
4246 case YearSection2Digits:
4247 case YearSection: year = newVal; break;
4248 case MonthSection: month = newVal; break;
4250 case DayOfWeekSectionShort:
4251 case DayOfWeekSectionLong:
4253 // have to keep legacy behavior. setting the
4254 // date to 32 should return false. Setting it
4255 // to 31 for february should return true
4260 case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
4262 qWarning("QDateTimeParser::setDigit() Internal error (%s)",
4263 qPrintable(sectionName(node.type)));
4267 if (!(node.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) {
4268 if (day < cachedDay)
4270 const int max = QDate(year, month, 1).daysInMonth();
4275 if (QDate::isValid(year, month, day) && QTime::isValid(hour, minute, second, msec)) {
4276 v = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
4287 Returns the absolute maximum for a section
4290 int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
4292 const SectionNode &sn = sectionNode(s);
4295 case Hour12Section: return 23; // this is special-cased in
4296 // parseSection. We want it to be
4297 // 23 for the stepBy case.
4299 case SecondSection: return 59;
4300 case MSecSection: return 999;
4301 case YearSection2Digits:
4302 case YearSection: return 9999; // sectionMaxSize will prevent
4303 // people from typing in a larger
4304 // number in count == 2 sections.
4305 // stepBy() will work on real years anyway
4306 case MonthSection: return 12;
4308 case DayOfWeekSectionShort:
4309 case DayOfWeekSectionLong: return cur.isValid() ? cur.date().daysInMonth() : 31;
4310 case AmPmSection: return 1;
4313 qWarning("QDateTimeParser::absoluteMax() Internal error (%s)",
4314 qPrintable(sectionName(sn.type)));
4321 Returns the absolute minimum for a section
4324 int QDateTimeParser::absoluteMin(int s) const
4326 const SectionNode &sn = sectionNode(s);
4333 case YearSection2Digits:
4334 case YearSection: return 0;
4337 case DayOfWeekSectionShort:
4338 case DayOfWeekSectionLong: return 1;
4339 case AmPmSection: return 0;
4342 qWarning("QDateTimeParser::absoluteMin() Internal error (%s, %0x)",
4343 qPrintable(sectionName(sn.type)), sn.type);
4350 Returns the sectionNode for the Section \a s.
4353 const QDateTimeParser::SectionNode &QDateTimeParser::sectionNode(int sectionIndex) const
4355 if (sectionIndex < 0) {
4356 switch (sectionIndex) {
4357 case FirstSectionIndex:
4359 case LastSectionIndex:
4361 case NoSectionIndex:
4364 } else if (sectionIndex < sectionNodes.size()) {
4365 return sectionNodes.at(sectionIndex);
4368 qWarning("QDateTimeParser::sectionNode() Internal error (%d)",
4373 QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const
4375 return sectionNode(sectionIndex).type;
4382 Returns the starting position for section \a s.
4385 int QDateTimeParser::sectionPos(int sectionIndex) const
4387 return sectionPos(sectionNode(sectionIndex));
4390 int QDateTimeParser::sectionPos(const SectionNode &sn) const
4393 case FirstSection: return 0;
4394 case LastSection: return displayText().size() - 1;
4398 qWarning("QDateTimeParser::sectionPos Internal error (%s)", qPrintable(sectionName(sn.type)));
4408 helper function for parseFormat. removes quotes that are
4409 not escaped and removes the escaping on those that are escaped
4413 static QString unquote(const QString &str)
4415 const QChar quote(QLatin1Char('\''));
4416 const QChar slash(QLatin1Char('\\'));
4417 const QChar zero(QLatin1Char('0'));
4420 const int max = str.size();
4421 for (int i=0; i<max; ++i) {
4422 if (str.at(i) == quote) {
4423 if (status != quote) {
4425 } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
4426 ret[ret.size() - 1] = quote;
4439 Parses the format \a newFormat. If successful, returns true and
4440 sets up the format. Else keeps the old format and returns false.
4444 static inline int countRepeat(const QString &str, int index, int maxCount)
4447 const QChar ch(str.at(index));
4448 const int max = qMin(index + maxCount, str.size());
4449 while (index + count < max && str.at(index + count) == ch) {
4455 static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote)
4457 QString str(string.mid(from, size));
4458 if (lastQuote >= from)
4464 bool QDateTimeParser::parseFormat(const QString &newFormat)
4466 const QLatin1Char quote('\'');
4467 const QLatin1Char slash('\\');
4468 const QLatin1Char zero('0');
4469 if (newFormat == displayFormat && !newFormat.isEmpty()) {
4473 QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData());
4475 QVector<SectionNode> newSectionNodes;
4476 Sections newDisplay = 0;
4477 QStringList newSeparators;
4481 const int max = newFormat.size();
4483 for (i = 0; i<max; ++i) {
4484 if (newFormat.at(i) == quote) {
4487 if (status != quote) {
4489 } else if (newFormat.at(i - 1) != slash) {
4492 } else if (status != quote) {
4493 const char sect = newFormat.at(i).toLatin1();
4497 if (parserType != QVariant::Date) {
4498 const Section hour = (sect == 'h') ? Hour12Section : Hour24Section;
4499 const SectionNode sn = { hour, i - add, countRepeat(newFormat, i, 2), 0 };
4500 newSectionNodes.append(sn);
4501 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4508 if (parserType != QVariant::Date) {
4509 const SectionNode sn = { MinuteSection, i - add, countRepeat(newFormat, i, 2), 0 };
4510 newSectionNodes.append(sn);
4511 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4514 newDisplay |= MinuteSection;
4518 if (parserType != QVariant::Date) {
4519 const SectionNode sn = { SecondSection, i - add, countRepeat(newFormat, i, 2), 0 };
4520 newSectionNodes.append(sn);
4521 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4524 newDisplay |= SecondSection;
4529 if (parserType != QVariant::Date) {
4530 const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3, 0 };
4531 newSectionNodes.append(sn);
4532 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4535 newDisplay |= MSecSection;
4540 if (parserType != QVariant::Date) {
4541 const bool cap = (sect == 'A');
4542 const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0), 0 };
4543 newSectionNodes.append(sn);
4544 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4545 newDisplay |= AmPmSection;
4546 if (i + 1 < newFormat.size()
4547 && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
4554 if (parserType != QVariant::Time) {
4555 const int repeat = countRepeat(newFormat, i, 4);
4557 const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits,
4558 i - add, repeat == 4 ? 4 : 2, 0 };
4559 newSectionNodes.append(sn);
4560 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4563 newDisplay |= sn.type;
4568 if (parserType != QVariant::Time) {
4569 const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4), 0 };
4570 newSectionNodes.append(sn);
4571 newSeparators.append(unquote(newFormat.mid(index, i - index)));
4574 newDisplay |= MonthSection;
4578 if (parserType != QVariant::Time) {
4579 const int repeat = countRepeat(newFormat, i, 4);
4580 const Section sectionType = (repeat == 4 ? DayOfWeekSectionLong
4581 : (repeat == 3 ? DayOfWeekSectionShort : DaySection));
4582 const SectionNode sn = { sectionType, i - add, repeat, 0 };
4583 newSectionNodes.append(sn);
4584 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4587 newDisplay |= sn.type;
4596 if (newSectionNodes.isEmpty() && context == DateTimeEdit) {
4600 if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
4601 const int max = newSectionNodes.size();
4602 for (int i=0; i<max; ++i) {
4603 SectionNode &node = newSectionNodes[i];
4604 if (node.type == Hour12Section)
4605 node.type = Hour24Section;
4609 if (index < newFormat.size()) {
4610 appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote);
4612 newSeparators.append(QString());
4615 displayFormat = newFormat;
4616 separators = newSeparators;
4617 sectionNodes = newSectionNodes;
4618 display = newDisplay;
4621 // for (int i=0; i<sectionNodes.size(); ++i) {
4622 // QDTPDEBUG << sectionName(sectionNodes.at(i).type) << sectionNodes.at(i).count;
4625 QDTPDEBUG << newFormat << displayFormat;
4626 QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData());
4634 Returns the size of section \a s.
4637 int QDateTimeParser::sectionSize(int sectionIndex) const
4639 if (sectionIndex < 0)
4642 if (sectionIndex >= sectionNodes.size()) {
4643 qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex);
4647 if (sectionIndex == sectionNodes.size() - 1) {
4648 // In some cases there is a difference between displayText() and text.
4649 // e.g. when text is 2000/01/31 and displayText() is "2000/2/31" - text
4650 // is the previous value and displayText() is the new value.
4651 // The size difference is always due to leading zeroes.
4652 int sizeAdjustment = 0;
4653 if (displayText().size() != text.size()) {
4654 // Any zeroes added before this section will affect our size.
4655 int preceedingZeroesAdded = 0;
4656 if (sectionNodes.size() > 1 && context == DateTimeEdit) {
4657 for (QVector<SectionNode>::ConstIterator sectionIt = sectionNodes.constBegin();
4658 sectionIt != sectionNodes.constBegin() + sectionIndex; ++sectionIt) {
4659 preceedingZeroesAdded += sectionIt->zeroesAdded;
4662 sizeAdjustment = preceedingZeroesAdded;
4665 return displayText().size() + sizeAdjustment - sectionPos(sectionIndex) - separators.last().size();
4667 return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex)
4668 - separators.at(sectionIndex + 1).size();
4673 int QDateTimeParser::sectionMaxSize(Section s, int count) const
4675 #ifndef QT_NO_TEXTDATE
4682 case LastSection: return 0;
4685 const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(),
4686 getAmPmText(PmText, LowerCase).size());
4687 const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(),
4688 getAmPmText(PmText, UpperCase).size());
4689 return qMin(4, qMin(lowerMax, upperMax));
4696 case DaySection: return 2;
4697 case DayOfWeekSectionShort:
4698 case DayOfWeekSectionLong:
4699 #ifdef QT_NO_TEXTDATE
4709 #ifdef QT_NO_TEXTDATE
4714 const QLocale l = locale();
4715 for (int i=1; i<=mcount; ++i) {
4716 const QString str = (s == MonthSection
4717 ? l.monthName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat)
4718 : l.dayName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat));
4719 ret = qMax(str.size(), ret);
4724 case MSecSection: return 3;
4725 case YearSection: return 4;
4726 case YearSection2Digits: return 2;
4728 case CalendarPopupSection:
4730 case TimeSectionMask:
4731 case DateSectionMask:
4732 qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s",
4733 sectionName(s).toLatin1().constData());
4735 case NoSectionIndex:
4736 case FirstSectionIndex:
4737 case LastSectionIndex:
4738 case CalendarPopupIndex:
4739 // these cases can't happen
4746 int QDateTimeParser::sectionMaxSize(int index) const
4748 const SectionNode &sn = sectionNode(index);
4749 return sectionMaxSize(sn.type, sn.count);
4755 Returns the text of section \a s. This function operates on the
4756 arg text rather than edit->text().
4760 QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const
4762 const SectionNode &sn = sectionNode(sectionIndex);
4764 case NoSectionIndex:
4765 case FirstSectionIndex:
4766 case LastSectionIndex:
4771 return text.mid(index, sectionSize(sectionIndex));
4774 QString QDateTimeParser::sectionText(int sectionIndex) const
4776 const SectionNode &sn = sectionNode(sectionIndex);
4778 case NoSectionIndex:
4779 case FirstSectionIndex:
4780 case LastSectionIndex:
4785 return displayText().mid(sn.pos, sectionSize(sectionIndex));
4789 #ifndef QT_NO_TEXTDATE
4791 \internal:skipToNextSection
4793 Parses the part of \a text that corresponds to \a s and returns
4794 the value of that field. Sets *stateptr to the right state if
4798 int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex,
4799 QString &text, int &cursorPosition, int index,
4800 State &state, int *usedptr) const
4804 const SectionNode &sn = sectionNode(sectionIndex);
4805 if ((sn.type & Internal) == Internal) {
4806 qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
4807 qPrintable(sectionName(sn.type)), sectionIndex);
4811 const int sectionmaxsize = sectionMaxSize(sectionIndex);
4812 QString sectiontext = text.mid(index, sectionmaxsize);
4813 int sectiontextSize = sectiontext.size();
4815 QDTPDEBUG << "sectionValue for" << sectionName(sn.type)
4816 << "with text" << text << "and st" << sectiontext
4817 << text.mid(index, sectionmaxsize)
4823 const int ampm = findAmPm(sectiontext, sectionIndex, &used);
4825 case AM: // sectiontext == AM
4826 case PM: // sectiontext == PM
4830 case PossibleAM: // sectiontext => AM
4831 case PossiblePM: // sectiontext => PM
4833 state = Intermediate;
4835 case PossibleBoth: // sectiontext => AM|PM
4837 state = Intermediate;
4841 QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1";
4844 QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm);
4847 if (state != Invalid) {
4849 text.replace(index, used, sectiontext.left(used));
4853 case DayOfWeekSectionShort:
4854 case DayOfWeekSectionLong:
4855 if (sn.count >= 3) {
4856 if (sn.type == MonthSection) {
4858 const QDate minDate = getMinimum().date();
4859 if (currentValue.date().year() == minDate.year()) {
4860 min = minDate.month();
4862 num = findMonth(sectiontext.toLower(), min, sectionIndex, §iontext, &used);
4864 num = findDay(sectiontext.toLower(), 1, sectionIndex, §iontext, &used);
4868 state = (used == sectiontext.size() ? Acceptable : Intermediate);
4870 text.replace(index, used, sectiontext.left(used));
4872 state = Intermediate;
4878 case YearSection2Digits:
4884 if (sectiontextSize == 0) {
4887 state = Intermediate;
4889 const int absMax = absoluteMax(sectionIndex);
4895 QString digitsStr(sectiontext);
4896 for (int i = 0; i < sectiontextSize; ++i) {
4897 if (digitsStr.at(i).isSpace()) {
4898 sectiontextSize = i;
4903 const int max = qMin(sectionmaxsize, sectiontextSize);
4904 for (int digits = max; digits >= 1; --digits) {
4905 digitsStr.truncate(digits);
4906 int tmp = (int)loc.toUInt(digitsStr, &ok);
4907 if (ok && sn.type == Hour12Section) {
4911 } else if (tmp == 12) {
4915 if (ok && tmp <= absMax) {
4916 QDTPDEBUG << sectiontext.left(digits) << tmp << digits;
4924 QChar first(sectiontext.at(0));
4925 if (separators.at(sectionIndex + 1).startsWith(first)) {
4927 state = Intermediate;
4930 QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok;
4934 const FieldInfo fi = fieldInfo(sectionIndex);
4935 const bool done = (used == sectionmaxsize);
4936 if (!done && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002
4937 for (int i=used; i<sectionmaxsize; ++i) {
4941 const int absMin = absoluteMin(sectionIndex);
4943 state = done ? Invalid : Intermediate;
4945 QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absMin;
4946 } else if (num > absMax) {
4947 state = Intermediate;
4948 } else if (!done && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
4949 if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
4951 const int missingZeroes = sectionmaxsize - digitsStr.size();
4952 text.insert(index, QString().fill(QLatin1Char('0'), missingZeroes));
4953 used = sectionmaxsize;
4954 cursorPosition += missingZeroes;
4955 ++(const_cast<QDateTimeParser*>(this)->sectionNodes[sectionIndex].zeroesAdded);
4957 state = Intermediate;;
4966 qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
4967 qPrintable(sectionName(sn.type)), sectionIndex);
4974 return (state != Invalid ? num : -1);
4976 #endif // QT_NO_TEXTDATE
4978 #ifndef QT_NO_DATESTRING
4983 QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPosition,
4984 const QDateTime ¤tValue, bool fixup) const
4986 const QDateTime minimum = getMinimum();
4987 const QDateTime maximum = getMaximum();
4989 State state = Acceptable;
4991 QDateTime newCurrentValue;
4993 bool conflicts = false;
4994 const int sectionNodesCount = sectionNodes.size();
4996 QDTPDEBUG << "parse" << input;
4998 int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits;
4999 getDateFromJulianDay(currentValue.date().toJulianDay(), &year, &month, &day);
5000 year2digits = year % 100;
5001 hour = currentValue.time().hour();
5003 minute = currentValue.time().minute();
5004 second = currentValue.time().second();
5005 msec = currentValue.time().msec();
5006 dayofweek = currentValue.date().dayOfWeek();
5009 Sections isSet = NoSection;
5013 for (int index=0; state != Invalid && index<sectionNodesCount; ++index) {
5014 if (QStringRef(&input, pos, separators.at(index).size()) != separators.at(index)) {
5015 QDTPDEBUG << "invalid because" << input.mid(pos, separators.at(index).size())
5016 << "!=" << separators.at(index)
5017 << index << pos << currentSectionIndex;
5021 pos += separators.at(index).size();
5022 sectionNodes[index].pos = pos;
5024 const SectionNode sn = sectionNodes.at(index);
5027 num = parseSection(currentValue, index, input, cursorPosition, pos, tmpstate, &used);
5028 QDTPDEBUG << "sectionValue" << sectionName(sectionType(index)) << input
5029 << "pos" << pos << "used" << used << stateName(tmpstate);
5030 if (fixup && tmpstate == Intermediate && used < sn.count) {
5031 const FieldInfo fi = fieldInfo(index);
5032 if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
5033 const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0'));
5034 input.replace(pos, used, newText);
5038 pos += qMax(0, used);
5040 state = qMin<State>(state, tmpstate);
5041 if (state == Intermediate && context == FromString) {
5046 QDTPDEBUG << index << sectionName(sectionType(index)) << "is set to"
5047 << pos << "state is" << stateName(state);
5050 if (state != Invalid) {
5052 case Hour24Section: current = &hour; break;
5053 case Hour12Section: current = &hour12; break;
5054 case MinuteSection: current = &minute; break;
5055 case SecondSection: current = &second; break;
5056 case MSecSection: current = &msec; break;
5057 case YearSection: current = &year; break;
5058 case YearSection2Digits: current = &year2digits; break;
5059 case MonthSection: current = &month; break;
5060 case DayOfWeekSectionShort:
5061 case DayOfWeekSectionLong: current = &dayofweek; break;
5062 case DaySection: current = &day; num = qMax<int>(1, num); break;
5063 case AmPmSection: current = &m; break;
5065 qWarning("QDateTimeParser::parse Internal error (%s)",
5066 qPrintable(sectionName(sn.type)));
5070 qWarning("QDateTimeParser::parse Internal error 2");
5073 if (isSet & sn.type && *current != num) {
5074 QDTPDEBUG << "CONFLICT " << sectionName(sn.type) << *current << num;
5076 if (index != currentSectionIndex || num == -1) {
5086 if (state != Invalid && QStringRef(&input, pos, input.size() - pos) != separators.last()) {
5087 QDTPDEBUG << "invalid because" << input.mid(pos)
5088 << "!=" << separators.last() << pos;
5092 if (state != Invalid) {
5093 if (parserType != QVariant::Time) {
5094 if (year % 100 != year2digits) {
5095 switch (isSet & (YearSection2Digits|YearSection)) {
5096 case YearSection2Digits:
5097 year = (year / 100) * 100;
5098 year += year2digits;
5100 case ((uint)YearSection2Digits|(uint)YearSection): {
5102 const SectionNode &sn = sectionNode(currentSectionIndex);
5103 if (sn.type == YearSection2Digits) {
5104 year = (year / 100) * 100;
5105 year += year2digits;
5113 const QDate date(year, month, day);
5114 const int diff = dayofweek - date.dayOfWeek();
5115 if (diff != 0 && state == Acceptable && isSet & (DayOfWeekSectionShort|DayOfWeekSectionLong)) {
5116 conflicts = isSet & DaySection;
5117 const SectionNode &sn = sectionNode(currentSectionIndex);
5118 if (sn.type & (DayOfWeekSectionShort|DayOfWeekSectionLong) || currentSectionIndex == -1) {
5119 // dayofweek should be preferred
5123 } else if (day > date.daysInMonth()) {
5126 QDTPDEBUG << year << month << day << dayofweek
5127 << diff << QDate(year, month, day).dayOfWeek();
5130 bool needfixday = false;
5131 if (sectionType(currentSectionIndex) & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong)) {
5133 } else if (cachedDay > day) {
5138 if (!QDate::isValid(year, month, day)) {
5142 if (day > 28 && QDate::isValid(year, month, 1)) {
5147 if (context == FromString) {
5151 if (state == Acceptable && fixday) {
5152 day = qMin<int>(day, QDate(year, month, 1).daysInMonth());
5154 const QLocale loc = locale();
5155 for (int i=0; i<sectionNodesCount; ++i) {
5156 const Section thisSectionType = sectionType(i);
5157 if (thisSectionType & (DaySection)) {
5158 input.replace(sectionPos(i), sectionSize(i), loc.toString(day));
5159 } else if (thisSectionType & (DayOfWeekSectionShort|DayOfWeekSectionLong)) {
5160 const int dayOfWeek = QDate(year, month, day).dayOfWeek();
5161 const QLocale::FormatType dayFormat = (thisSectionType == DayOfWeekSectionShort
5162 ? QLocale::ShortFormat : QLocale::LongFormat);
5163 const QString dayName(loc.dayName(dayOfWeek, dayFormat));
5164 input.replace(sectionPos(i), sectionSize(i), dayName);
5168 state = qMin(Intermediate, state);
5173 if (parserType != QVariant::Date) {
5174 if (isSet & Hour12Section) {
5175 const bool hasHour = isSet & Hour24Section;
5178 ampm = (hour < 12 ? 0 : 1);
5180 ampm = 0; // no way to tell if this is am or pm so I assume am
5183 hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12);
5186 } else if (hour != hour12) {
5189 } else if (ampm != -1) {
5190 if (!(isSet & (Hour24Section))) {
5191 hour = (12 * ampm); // special case. Only ap section
5192 } else if ((ampm == 0) != (hour < 12)) {
5199 newCurrentValue = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
5200 QDTPDEBUG << year << month << day << hour << minute << second << msec;
5202 QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
5203 newCurrentValue.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
5204 stateName(state).toLatin1().constData());
5207 if (newCurrentValue.isValid()) {
5208 if (context != FromString && state != Invalid && newCurrentValue < minimum) {
5209 const QLatin1Char space(' ');
5210 if (newCurrentValue >= minimum)
5211 qWarning("QDateTimeParser::parse Internal error 3 (%s %s)",
5212 qPrintable(newCurrentValue.toString()), qPrintable(minimum.toString()));
5216 for (int i=0; i<sectionNodesCount && !done; ++i) {
5217 const SectionNode &sn = sectionNodes.at(i);
5218 QString t = sectionText(input, i, sn.pos).toLower();
5219 if ((t.size() < sectionMaxSize(i) && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric))
5220 || t.contains(space)) {
5223 switch (findAmPm(t, i)) {
5235 case PossibleBoth: {
5236 const QDateTime copy(newCurrentValue.addSecs(12 * 60 * 60));
5237 if (copy >= minimum && copy <= maximum) {
5238 state = Intermediate;
5244 if (sn.count >= 3) {
5245 int tmp = newCurrentValue.date().month();
5246 // I know the first possible month makes the date too early
5247 while ((tmp = findMonth(t, tmp + 1, i)) != -1) {
5248 const QDateTime copy(newCurrentValue.addMonths(tmp - newCurrentValue.date().month()));
5249 if (copy >= minimum && copy <= maximum)
5250 break; // break out of while
5255 state = Intermediate;
5264 if (sn.type & TimeSectionMask) {
5265 if (newCurrentValue.daysTo(minimum) != 0) {
5268 toMin = newCurrentValue.time().msecsTo(minimum.time());
5269 if (newCurrentValue.daysTo(maximum) > 0) {
5270 toMax = -1; // can't get to max
5272 toMax = newCurrentValue.time().msecsTo(maximum.time());
5275 toMin = newCurrentValue.daysTo(minimum);
5276 toMax = newCurrentValue.daysTo(maximum);
5278 const int maxChange = QDateTimeParser::maxChange(i);
5279 if (toMin > maxChange) {
5280 QDTPDEBUG << "invalid because toMin > maxChange" << toMin
5281 << maxChange << t << newCurrentValue << minimum;
5285 } else if (toMax > maxChange) {
5286 toMax = -1; // can't get to max
5289 const int min = getDigit(minimum, i);
5291 qWarning("QDateTimeParser::parse Internal error 4 (%s)",
5292 qPrintable(sectionName(sn.type)));
5298 int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, newCurrentValue);
5299 int pos = cursorPosition - sn.pos;
5300 if (pos < 0 || pos >= t.size())
5302 if (!potentialValue(t.simplified(), min, max, i, newCurrentValue, pos)) {
5303 QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max
5304 << sectionName(sn.type) << "returned" << toMax << toMin << pos;
5309 state = Intermediate;
5316 if (context == FromString) {
5318 Q_ASSERT(getMaximum().date().toJulianDay() == 4642999);
5319 if (newCurrentValue.date().toJulianDay() > 4642999)
5322 if (newCurrentValue > getMaximum())
5326 QDTPDEBUG << "not checking intermediate because newCurrentValue is" << newCurrentValue << getMinimum() << getMaximum();
5332 node.conflicts = conflicts;
5333 node.value = newCurrentValue.toTimeSpec(spec);
5337 #endif // QT_NO_DATESTRING
5339 #ifndef QT_NO_TEXTDATE
5342 finds the first possible monthname that \a str1 can
5343 match. Starting from \a index; str should already by lowered
5346 int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex,
5347 QString *usedMonth, int *used) const
5351 if (!str1.isEmpty()) {
5352 const SectionNode &sn = sectionNode(sectionIndex);
5353 if (sn.type != MonthSection) {
5354 qWarning("QDateTimeParser::findMonth Internal error");
5358 QLocale::FormatType type = sn.count == 3 ? QLocale::ShortFormat : QLocale::LongFormat;
5359 QLocale l = locale();
5361 for (int month=startMonth; month<=12; ++month) {
5362 QString str2 = l.monthName(month, type).toLower();
5364 if (str1.startsWith(str2)) {
5366 QDTPDEBUG << "used is set to" << str2.size();
5367 *used = str2.size();
5370 *usedMonth = l.monthName(month, type);
5374 if (context == FromString)
5377 const int limit = qMin(str1.size(), str2.size());
5379 QDTPDEBUG << "limit is" << limit << str1 << str2;
5381 for (int i=0; i<limit; ++i) {
5382 if (str1.at(i) != str2.at(i)) {
5384 if (i > bestCount) {
5395 *usedMonth = l.monthName(month, type);
5399 if (usedMonth && bestMatch != -1)
5400 *usedMonth = l.monthName(bestMatch, type);
5403 QDTPDEBUG << "used is set to" << bestCount;
5409 int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const
5413 if (!str1.isEmpty()) {
5414 const SectionNode &sn = sectionNode(sectionIndex);
5415 if (!(sn.type & (DaySection|DayOfWeekSectionShort|DayOfWeekSectionLong))) {
5416 qWarning("QDateTimeParser::findDay Internal error");
5419 const QLocale l = locale();
5420 for (int day=startDay; day<=7; ++day) {
5421 const QString str2 = l.dayName(day, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
5423 if (str1.startsWith(str2.toLower())) {
5425 *used = str2.size();
5431 if (context == FromString)
5434 const int limit = qMin(str1.size(), str2.size());
5436 for (int i=0; i<limit; ++i) {
5437 if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) {
5438 if (i > bestCount) {
5456 if (usedDay && bestMatch != -1) {
5457 *usedDay = l.dayName(bestMatch, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
5465 #endif // QT_NO_TEXTDATE
5471 0 if str == QDateTimeEdit::tr("AM")
5472 1 if str == QDateTimeEdit::tr("PM")
5473 2 if str can become QDateTimeEdit::tr("AM")
5474 3 if str can become QDateTimeEdit::tr("PM")
5475 4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM")
5476 -1 can't become anything sensible
5480 int QDateTimeParser::findAmPm(QString &str, int index, int *used) const
5482 const SectionNode &s = sectionNode(index);
5483 if (s.type != AmPmSection) {
5484 qWarning("QDateTimeParser::findAmPm Internal error");
5489 if (str.trimmed().isEmpty()) {
5490 return PossibleBoth;
5492 const QLatin1Char space(' ');
5493 int size = sectionMaxSize(index);
5500 ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase);
5501 ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase);
5502 for (int i=0; i<2; ++i)
5503 ampm[i].truncate(size);
5505 QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
5507 if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) {
5508 str = ampm[amindex];
5510 } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) {
5511 str = ampm[pmindex];
5513 } else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) {
5516 size = qMin(size, str.size());
5518 bool broken[2] = {false, false};
5519 for (int i=0; i<size; ++i) {
5520 if (str.at(i) != space) {
5521 for (int j=0; j<2; ++j) {
5523 int index = ampm[j].indexOf(str.at(i));
5524 QDTPDEBUG << "looking for" << str.at(i)
5525 << "in" << ampm[j] << "and got" << index;
5527 if (str.at(i).category() == QChar::Letter_Uppercase) {
5528 index = ampm[j].indexOf(str.at(i).toLower());
5529 QDTPDEBUG << "trying with" << str.at(i).toLower()
5530 << "in" << ampm[j] << "and got" << index;
5531 } else if (str.at(i).category() == QChar::Letter_Lowercase) {
5532 index = ampm[j].indexOf(str.at(i).toUpper());
5533 QDTPDEBUG << "trying with" << str.at(i).toUpper()
5534 << "in" << ampm[j] << "and got" << index;
5538 if (broken[amindex] && broken[pmindex]) {
5539 QDTPDEBUG << str << "didn't make it";
5544 str[i] = ampm[j].at(index); // fix case
5547 ampm[j].remove(index, 1);
5552 if (!broken[pmindex] && !broken[amindex])
5553 return PossibleBoth;
5554 return (!broken[amindex] ? PossibleAM : PossiblePM);
5559 Max number of units that can be changed by this section.
5562 int QDateTimeParser::maxChange(int index) const
5564 const SectionNode &sn = sectionNode(index);
5566 // Time. unit is msec
5567 case MSecSection: return 999;
5568 case SecondSection: return 59 * 1000;
5569 case MinuteSection: return 59 * 60 * 1000;
5570 case Hour24Section: case Hour12Section: return 59 * 60 * 60 * 1000;
5572 // Date. unit is day
5573 case DayOfWeekSectionShort:
5574 case DayOfWeekSectionLong: return 7;
5575 case DaySection: return 30;
5576 case MonthSection: return 365 - 31;
5577 case YearSection: return 9999 * 365;
5578 case YearSection2Digits: return 100 * 365;
5580 qWarning("QDateTimeParser::maxChange() Internal error (%s)",
5581 qPrintable(sectionName(sectionType(index))));
5587 QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
5590 const SectionNode &sn = sectionNode(index);
5591 const Section s = sn.type;
5601 case YearSection2Digits:
5603 if (s != YearSection) {
5604 ret |= AllowPartial;
5606 if (sn.count != 1) {
5617 ret |= (Numeric|AllowPartial);
5621 case DayOfWeekSectionShort:
5622 case DayOfWeekSectionLong:
5630 qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)",
5631 index, qPrintable(sectionName(sn.type)), sn.count);
5640 Get a number that str can become which is between min
5641 and max or -1 if this is not possible.
5645 QString QDateTimeParser::sectionFormat(int index) const
5647 const SectionNode &sn = sectionNode(index);
5648 return sectionFormat(sn.type, sn.count);
5651 QString QDateTimeParser::sectionFormat(Section s, int count) const
5655 case AmPmSection: return count == 1 ? QLatin1String("AP") : QLatin1String("ap");
5656 case MSecSection: fillChar = QLatin1Char('z'); break;
5657 case SecondSection: fillChar = QLatin1Char('s'); break;
5658 case MinuteSection: fillChar = QLatin1Char('m'); break;
5659 case Hour24Section: fillChar = QLatin1Char('H'); break;
5660 case Hour12Section: fillChar = QLatin1Char('h'); break;
5661 case DayOfWeekSectionShort:
5662 case DayOfWeekSectionLong:
5663 case DaySection: fillChar = QLatin1Char('d'); break;
5664 case MonthSection: fillChar = QLatin1Char('M'); break;
5665 case YearSection2Digits:
5666 case YearSection: fillChar = QLatin1Char('y'); break;
5668 qWarning("QDateTimeParser::sectionFormat Internal error (%s)",
5669 qPrintable(sectionName(s)));
5672 if (fillChar.isNull()) {
5673 qWarning("QDateTimeParser::sectionFormat Internal error 2");
5678 str.fill(fillChar, count);
5686 Returns true if str can be modified to represent a
5687 number that is within min and max.
5690 bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index,
5691 const QDateTime ¤tValue, int insert) const
5693 if (str.isEmpty()) {
5696 const int size = sectionMaxSize(index);
5697 int val = (int)locale().toUInt(str);
5698 const SectionNode &sn = sectionNode(index);
5699 if (sn.type == YearSection2Digits) {
5700 val += currentValue.date().year() - (currentValue.date().year() % 100);
5702 if (val >= min && val <= max && str.size() == size) {
5704 } else if (val > max) {
5706 } else if (str.size() == size && val < min) {
5710 const int len = size - str.size();
5711 for (int i=0; i<len; ++i) {
5712 for (int j=0; j<10; ++j) {
5713 if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) {
5715 } else if (insert >= 0) {
5717 tmp.insert(insert, QLatin1Char('0' + j));
5718 if (potentialValue(tmp, min, max, index, currentValue, insert))
5727 bool QDateTimeParser::skipToNextSection(int index, const QDateTime ¤t, const QString &text) const
5729 Q_ASSERT(current >= getMinimum() && current <= getMaximum());
5731 const SectionNode &node = sectionNode(index);
5732 Q_ASSERT(text.size() < sectionMaxSize(index));
5734 const QDateTime maximum = getMaximum();
5735 const QDateTime minimum = getMinimum();
5736 QDateTime tmp = current;
5737 int min = absoluteMin(index);
5738 setDigit(tmp, index, min);
5739 if (tmp < minimum) {
5740 min = getDigit(minimum, index);
5743 int max = absoluteMax(index, current);
5744 setDigit(tmp, index, max);
5745 if (tmp > maximum) {
5746 max = getDigit(maximum, index);
5748 int pos = cursorPosition() - node.pos;
5749 if (pos < 0 || pos >= text.size())
5752 const bool potential = potentialValue(text, min, max, index, current, pos);
5755 /* If the value potentially can become another valid entry we
5756 * don't want to skip to the next. E.g. In a M field (month
5757 * without leading 0 if you type 1 we don't want to autoskip but
5758 * if you type 3 we do
5764 For debugging. Returns the name of the section \a s.
5767 QString QDateTimeParser::sectionName(int s) const
5770 case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection");
5771 case QDateTimeParser::DaySection: return QLatin1String("DaySection");
5772 case QDateTimeParser::DayOfWeekSectionShort: return QLatin1String("DayOfWeekSectionShort");
5773 case QDateTimeParser::DayOfWeekSectionLong: return QLatin1String("DayOfWeekSectionLong");
5774 case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section");
5775 case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section");
5776 case QDateTimeParser::MSecSection: return QLatin1String("MSecSection");
5777 case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection");
5778 case QDateTimeParser::MonthSection: return QLatin1String("MonthSection");
5779 case QDateTimeParser::SecondSection: return QLatin1String("SecondSection");
5780 case QDateTimeParser::YearSection: return QLatin1String("YearSection");
5781 case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits");
5782 case QDateTimeParser::NoSection: return QLatin1String("NoSection");
5783 case QDateTimeParser::FirstSection: return QLatin1String("FirstSection");
5784 case QDateTimeParser::LastSection: return QLatin1String("LastSection");
5785 default: return QLatin1String("Unknown section ") + QString::number(s);
5791 For debugging. Returns the name of the state \a s.
5794 QString QDateTimeParser::stateName(int s) const
5797 case Invalid: return QLatin1String("Invalid");
5798 case Intermediate: return QLatin1String("Intermediate");
5799 case Acceptable: return QLatin1String("Acceptable");
5800 default: return QLatin1String("Unknown state ") + QString::number(s);
5804 #ifndef QT_NO_DATESTRING
5805 bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
5807 QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN);
5810 const StateNode tmp = parse(text, copy, val, false);
5811 if (tmp.state != Acceptable || tmp.conflicts) {
5815 const QTime t = tmp.value.time();
5823 const QDate d = tmp.value.date();
5831 #endif // QT_NO_DATESTRING
5833 QDateTime QDateTimeParser::getMinimum() const
5835 return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec);
5838 QDateTime QDateTimeParser::getMaximum() const
5840 return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec);
5843 QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
5846 return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am"));
5848 return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm"));
5855 I give arg2 preference because arg1 is always a QDateTime.
5858 bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2)
5860 return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count);
5863 #endif // QT_BOOTSTRAPPED