| /**************************************************************************** |
| ** |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** This file is part of the QtCore module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** GNU Lesser General Public License Usage |
| ** This file may be used under the terms of the GNU Lesser General Public |
| ** License version 2.1 as published by the Free Software Foundation and |
| ** appearing in the file LICENSE.LGPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU Lesser |
| ** General Public License version 2.1 requirements will be met: |
| ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| ** |
| ** In addition, as a special exception, Nokia gives you certain additional |
| ** rights. These rights are described in the Nokia Qt LGPL Exception |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU General |
| ** Public License version 3.0 as published by the Free Software Foundation |
| ** and appearing in the file LICENSE.GPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU General |
| ** Public License version 3.0 requirements will be met: |
| ** http://www.gnu.org/copyleft/gpl.html. |
| ** |
| ** Other Usage |
| ** Alternatively, this file may be used in accordance with the terms and |
| ** conditions contained in a signed written agreement between you and Nokia. |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qplatformdefs.h" |
| #include "private/qdatetime_p.h" |
| |
| #include "qdatastream.h" |
| #include "qset.h" |
| #include "qlocale.h" |
| #include "qdatetime.h" |
| #include "qregexp.h" |
| #include "qdebug.h" |
| #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) |
| #include <qt_windows.h> |
| #endif |
| #ifndef Q_WS_WIN |
| #include <locale.h> |
| #endif |
| |
| #include <time.h> |
| #if defined(Q_OS_WINCE) |
| #include "qfunctions_wince.h" |
| #endif |
| |
| //#define QDATETIMEPARSER_DEBUG |
| #if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM) |
| # define QDTPDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__) |
| # define QDTPDEBUGN qDebug |
| #else |
| # define QDTPDEBUG if (false) qDebug() |
| # define QDTPDEBUGN if (false) qDebug |
| #endif |
| |
| #if defined(Q_WS_MAC) |
| #include <private/qcore_mac_p.h> |
| #endif |
| |
| #if defined(Q_OS_SYMBIAN) |
| #include <e32std.h> |
| #endif |
| |
| QT_BEGIN_NAMESPACE |
| |
| enum { |
| FIRST_YEAR = -4713, |
| FIRST_MONTH = 1, |
| FIRST_DAY = 2, // ### Qt 5: make FIRST_DAY = 1, by support jd == 0 as valid |
| SECS_PER_DAY = 86400, |
| MSECS_PER_DAY = 86400000, |
| SECS_PER_HOUR = 3600, |
| MSECS_PER_HOUR = 3600000, |
| SECS_PER_MIN = 60, |
| MSECS_PER_MIN = 60000, |
| JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromGregorianDate(1970, 1, 1) |
| }; |
| |
| static inline QDate fixedDate(int y, int m, int d) |
| { |
| QDate result(y, m, 1); |
| result.setDate(y, m, qMin(d, result.daysInMonth())); |
| return result; |
| } |
| |
| static inline uint julianDayFromGregorianDate(int year, int month, int day) |
| { |
| // Gregorian calendar starting from October 15, 1582 |
| // Algorithm from Henry F. Fliegel and Thomas C. Van Flandern |
| return (1461 * (year + 4800 + (month - 14) / 12)) / 4 |
| + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12 |
| - (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4 |
| + day - 32075; |
| } |
| |
| static uint julianDayFromDate(int year, int month, int day) |
| { |
| if (year < 0) |
| ++year; |
| |
| if (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day >= 15)))) { |
| return julianDayFromGregorianDate(year, month, day); |
| } else if (year < 1582 || (year == 1582 && (month < 10 || (month == 10 && day <= 4)))) { |
| // Julian calendar until October 4, 1582 |
| // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering |
| int a = (14 - month) / 12; |
| return (153 * (month + (12 * a) - 3) + 2) / 5 |
| + (1461 * (year + 4800 - a)) / 4 |
| + day - 32083; |
| } else { |
| // the day following October 4, 1582 is October 15, 1582 |
| return 0; |
| } |
| } |
| |
| static void getDateFromJulianDay(uint julianDay, int *year, int *month, int *day) |
| { |
| int y, m, d; |
| |
| if (julianDay >= 2299161) { |
| // Gregorian calendar starting from October 15, 1582 |
| // This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern |
| qulonglong ell, n, i, j; |
| ell = qulonglong(julianDay) + 68569; |
| n = (4 * ell) / 146097; |
| ell = ell - (146097 * n + 3) / 4; |
| i = (4000 * (ell + 1)) / 1461001; |
| ell = ell - (1461 * i) / 4 + 31; |
| j = (80 * ell) / 2447; |
| d = ell - (2447 * j) / 80; |
| ell = j / 11; |
| m = j + 2 - (12 * ell); |
| y = 100 * (n - 49) + i + ell; |
| } else { |
| // Julian calendar until October 4, 1582 |
| // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering |
| julianDay += 32082; |
| int dd = (4 * julianDay + 3) / 1461; |
| int ee = julianDay - (1461 * dd) / 4; |
| int mm = ((5 * ee) + 2) / 153; |
| d = ee - (153 * mm + 2) / 5 + 1; |
| m = mm + 3 - 12 * (mm / 10); |
| y = dd - 4800 + (mm / 10); |
| if (y <= 0) |
| --y; |
| } |
| if (year) |
| *year = y; |
| if (month) |
| *month = m; |
| if (day) |
| *day = d; |
| } |
| |
| |
| static const char monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| |
| #ifndef QT_NO_TEXTDATE |
| static const char * const qt_shortMonthNames[] = { |
| "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
| "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; |
| #endif |
| #ifndef QT_NO_DATESTRING |
| static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0); |
| #endif |
| |
| /***************************************************************************** |
| QDate member functions |
| *****************************************************************************/ |
| |
| /*! |
| \since 4.5 |
| |
| \enum QDate::MonthNameType |
| |
| This enum describes the types of the string representation used |
| for the month name. |
| |
| \value DateFormat This type of name can be used for date-to-string formatting. |
| \value StandaloneFormat This type is used when you need to enumerate months or weekdays. |
| Usually standalone names are represented in singular forms with |
| capitalized first letter. |
| */ |
| |
| /*! |
| \class QDate |
| \reentrant |
| \brief The QDate class provides date functions. |
| |
| |
| A QDate object contains a calendar date, i.e. year, month, and day |
| numbers, in the Gregorian calendar. (see \l{QDate G and J} {Use of |
| Gregorian and Julian Calendars} for dates prior to 15 October |
| 1582). It can read the current date from the system clock. It |
| provides functions for comparing dates, and for manipulating |
| dates. For example, it is possible to add and subtract days, |
| months, and years to dates. |
| |
| A QDate object is typically created either by giving the year, |
| month, and day numbers explicitly. Note that QDate interprets two |
| digit years as is, i.e., years 0 - 99. A QDate can also be |
| constructed with the static function currentDate(), which creates |
| a QDate object containing the system clock's date. An explicit |
| date can also be set using setDate(). The fromString() function |
| returns a QDate given a string and a date format which is used to |
| interpret the date within the string. |
| |
| The year(), month(), and day() functions provide access to the |
| year, month, and day numbers. Also, dayOfWeek() and dayOfYear() |
| functions are provided. The same information is provided in |
| textual format by the toString(), shortDayName(), longDayName(), |
| shortMonthName(), and longMonthName() functions. |
| |
| QDate provides a full set of operators to compare two QDate |
| objects where smaller means earlier, and larger means later. |
| |
| You can increment (or decrement) a date by a given number of days |
| using addDays(). Similarly you can use addMonths() and addYears(). |
| The daysTo() function returns the number of days between two |
| dates. |
| |
| The daysInMonth() and daysInYear() functions return how many days |
| there are in this date's month and year, respectively. The |
| isLeapYear() function indicates whether a date is in a leap year. |
| |
| \section1 |
| |
| \target QDate G and J |
| \section2 Use of Gregorian and Julian Calendars |
| |
| QDate uses the Gregorian calendar in all locales, beginning |
| on the date 15 October 1582. For dates up to and including 4 |
| October 1582, the Julian calendar is used. This means there is a |
| 10-day gap in the internal calendar between the 4th and the 15th |
| of October 1582. When you use QDateTime for dates in that epoch, |
| the day after 4 October 1582 is 15 October 1582, and the dates in |
| the gap are invalid. |
| |
| The Julian to Gregorian changeover date used here is the date when |
| the Gregorian calendar was first introduced, by Pope Gregory |
| XIII. That change was not universally accepted and some localities |
| only executed it at a later date (if at all). QDateTime |
| doesn't take any of these historical facts into account. If an |
| application must support a locale-specific dating system, it must |
| do so on its own, remembering to convert the dates using the |
| Julian day. |
| |
| \section2 No Year 0 |
| |
| There is no year 0. Dates in that year are considered invalid. The |
| year -1 is the year "1 before Christ" or "1 before current era." |
| The day before 0001-01-01 is December 31st, 1 BCE. |
| |
| \section2 Range of Valid Dates |
| |
| The range of valid dates is from January 2nd, 4713 BCE, to |
| sometime in the year 11 million CE. The Julian Day returned by |
| QDate::toJulianDay() is a number in the contiguous range from 1 to |
| \e{overflow}, even across QDateTime's "date holes". It is suitable |
| for use in applications that must convert a QDateTime to a date in |
| another calendar system, e.g., Hebrew, Islamic or Chinese. |
| |
| \sa QTime, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget |
| */ |
| |
| /*! |
| \fn QDate::QDate() |
| |
| Constructs a null date. Null dates are invalid. |
| |
| \sa isNull(), isValid() |
| */ |
| |
| /*! |
| Constructs a date with year \a y, month \a m and day \a d. |
| |
| If the specified date is invalid, the date is not set and |
| isValid() returns false. A date before 2 January 4713 B.C. is |
| considered invalid. |
| |
| \warning Years 0 to 99 are interpreted as is, i.e., years |
| 0-99. |
| |
| \sa isValid() |
| */ |
| |
| QDate::QDate(int y, int m, int d) |
| { |
| setDate(y, m, d); |
| } |
| |
| |
| /*! |
| \fn bool QDate::isNull() const |
| |
| Returns true if the date is null; otherwise returns false. A null |
| date is invalid. |
| |
| \note The behavior of this function is equivalent to isValid(). |
| |
| \sa isValid() |
| */ |
| |
| |
| /*! |
| Returns true if this date is valid; otherwise returns false. |
| |
| \sa isNull() |
| */ |
| |
| bool QDate::isValid() const |
| { |
| return !isNull(); |
| } |
| |
| |
| /*! |
| Returns the year of this date. Negative numbers indicate years |
| before 1 A.D. = 1 C.E., such that year -44 is 44 B.C. |
| |
| \sa month(), day() |
| */ |
| |
| int QDate::year() const |
| { |
| int y; |
| getDateFromJulianDay(jd, &y, 0, 0); |
| return y; |
| } |
| |
| /*! |
| Returns the number corresponding to the month of this date, using |
| the following convention: |
| |
| \list |
| \i 1 = "January" |
| \i 2 = "February" |
| \i 3 = "March" |
| \i 4 = "April" |
| \i 5 = "May" |
| \i 6 = "June" |
| \i 7 = "July" |
| \i 8 = "August" |
| \i 9 = "September" |
| \i 10 = "October" |
| \i 11 = "November" |
| \i 12 = "December" |
| \endlist |
| |
| \sa year(), day() |
| */ |
| |
| int QDate::month() const |
| { |
| int m; |
| getDateFromJulianDay(jd, 0, &m, 0); |
| return m; |
| } |
| |
| /*! |
| Returns the day of the month (1 to 31) of this date. |
| |
| \sa year(), month(), dayOfWeek() |
| */ |
| |
| int QDate::day() const |
| { |
| int d; |
| getDateFromJulianDay(jd, 0, 0, &d); |
| return d; |
| } |
| |
| /*! |
| Returns the weekday (1 to 7) for this date. |
| |
| \sa day(), dayOfYear(), Qt::DayOfWeek |
| */ |
| |
| int QDate::dayOfWeek() const |
| { |
| return (jd % 7) + 1; |
| } |
| |
| /*! |
| Returns the day of the year (1 to 365 or 366 on leap years) for |
| this date. |
| |
| \sa day(), dayOfWeek() |
| */ |
| |
| int QDate::dayOfYear() const |
| { |
| return jd - julianDayFromDate(year(), 1, 1) + 1; |
| } |
| |
| /*! |
| Returns the number of days in the month (28 to 31) for this date. |
| |
| \sa day(), daysInYear() |
| */ |
| |
| int QDate::daysInMonth() const |
| { |
| int y, m, d; |
| getDateFromJulianDay(jd, &y, &m, &d); |
| if (m == 2 && isLeapYear(y)) |
| return 29; |
| else |
| return monthDays[m]; |
| } |
| |
| /*! |
| Returns the number of days in the year (365 or 366) for this date. |
| |
| \sa day(), daysInMonth() |
| */ |
| |
| int QDate::daysInYear() const |
| { |
| int y, m, d; |
| getDateFromJulianDay(jd, &y, &m, &d); |
| return isLeapYear(y) ? 366 : 365; |
| } |
| |
| /*! |
| Returns the week number (1 to 53), and stores the year in |
| *\a{yearNumber} unless \a yearNumber is null (the default). |
| |
| Returns 0 if the date is invalid. |
| |
| In accordance with ISO 8601, weeks start on Monday and the first |
| Thursday of a year is always in week 1 of that year. Most years |
| have 52 weeks, but some have 53. |
| |
| *\a{yearNumber} is not always the same as year(). For example, 1 |
| January 2000 has week number 52 in the year 1999, and 31 December |
| 2002 has week number 1 in the year 2003. |
| |
| \legalese |
| Copyright (c) 1989 The Regents of the University of California. |
| All rights reserved. |
| |
| Redistribution and use in source and binary forms are permitted |
| provided that the above copyright notice and this paragraph are |
| duplicated in all such forms and that any documentation, |
| advertising materials, and other materials related to such |
| distribution and use acknowledge that the software was developed |
| by the University of California, Berkeley. The name of the |
| University may not be used to endorse or promote products derived |
| from this software without specific prior written permission. |
| THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR |
| IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
| |
| \sa isValid() |
| */ |
| |
| int QDate::weekNumber(int *yearNumber) const |
| { |
| if (!isValid()) |
| return 0; |
| |
| int year = QDate::year(); |
| int yday = dayOfYear() - 1; |
| int wday = dayOfWeek(); |
| if (wday == 7) |
| wday = 0; |
| int w; |
| |
| for (;;) { |
| int len; |
| int bot; |
| int top; |
| |
| len = isLeapYear(year) ? 366 : 365; |
| /* |
| ** What yday (-3 ... 3) does |
| ** the ISO year begin on? |
| */ |
| bot = ((yday + 11 - wday) % 7) - 3; |
| /* |
| ** What yday does the NEXT |
| ** ISO year begin on? |
| */ |
| top = bot - (len % 7); |
| if (top < -3) |
| top += 7; |
| top += len; |
| if (yday >= top) { |
| ++year; |
| w = 1; |
| break; |
| } |
| if (yday >= bot) { |
| w = 1 + ((yday - bot) / 7); |
| break; |
| } |
| --year; |
| yday += isLeapYear(year) ? 366 : 365; |
| } |
| if (yearNumber != 0) |
| *yearNumber = year; |
| return w; |
| } |
| |
| #ifndef QT_NO_TEXTDATE |
| /*! |
| \since 4.5 |
| |
| Returns the short name of the \a month for the representation specified |
| by \a type. |
| |
| The months are enumerated using the following convention: |
| |
| \list |
| \i 1 = "Jan" |
| \i 2 = "Feb" |
| \i 3 = "Mar" |
| \i 4 = "Apr" |
| \i 5 = "May" |
| \i 6 = "Jun" |
| \i 7 = "Jul" |
| \i 8 = "Aug" |
| \i 9 = "Sep" |
| \i 10 = "Oct" |
| \i 11 = "Nov" |
| \i 12 = "Dec" |
| \endlist |
| |
| The month names will be localized according to the system's locale |
| settings. |
| |
| \sa toString(), longMonthName(), shortDayName(), longDayName() |
| */ |
| |
| QString QDate::shortMonthName(int month, QDate::MonthNameType type) |
| { |
| if (month < 1 || month > 12) { |
| month = 1; |
| } |
| switch (type) { |
| case QDate::DateFormat: |
| return QLocale::system().monthName(month, QLocale::ShortFormat); |
| case QDate::StandaloneFormat: |
| return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat); |
| default: |
| break; |
| } |
| return QString(); |
| } |
| |
| /*! |
| Returns the short version of the name of the \a month. The |
| returned name is in normal type which can be used for date formatting. |
| |
| \sa toString(), longMonthName(), shortDayName(), longDayName() |
| */ |
| |
| QString QDate::shortMonthName(int month) |
| { |
| return shortMonthName(month, QDate::DateFormat); |
| } |
| |
| /*! |
| \since 4.5 |
| |
| Returns the long name of the \a month for the representation specified |
| by \a type. |
| |
| The months are enumerated using the following convention: |
| |
| \list |
| \i 1 = "January" |
| \i 2 = "February" |
| \i 3 = "March" |
| \i 4 = "April" |
| \i 5 = "May" |
| \i 6 = "June" |
| \i 7 = "July" |
| \i 8 = "August" |
| \i 9 = "September" |
| \i 10 = "October" |
| \i 11 = "November" |
| \i 12 = "December" |
| \endlist |
| |
| The month names will be localized according to the system's locale |
| settings. |
| |
| \sa toString(), shortMonthName(), shortDayName(), longDayName() |
| */ |
| |
| QString QDate::longMonthName(int month, MonthNameType type) |
| { |
| if (month < 1 || month > 12) { |
| month = 1; |
| } |
| switch (type) { |
| case QDate::DateFormat: |
| return QLocale::system().monthName(month, QLocale::LongFormat); |
| case QDate::StandaloneFormat: |
| return QLocale::system().standaloneMonthName(month, QLocale::LongFormat); |
| default: |
| break; |
| } |
| return QString(); |
| } |
| |
| /*! |
| Returns the long version of the name of the \a month. The |
| returned name is in normal type which can be used for date formatting. |
| |
| \sa toString(), shortMonthName(), shortDayName(), longDayName() |
| */ |
| |
| QString QDate::longMonthName(int month) |
| { |
| if (month < 1 || month > 12) { |
| month = 1; |
| } |
| return QLocale::system().monthName(month, QLocale::LongFormat); |
| } |
| |
| /*! |
| \since 4.5 |
| |
| Returns the short name of the \a weekday for the representation specified |
| by \a type. |
| |
| The days are enumerated using the following convention: |
| |
| \list |
| \i 1 = "Mon" |
| \i 2 = "Tue" |
| \i 3 = "Wed" |
| \i 4 = "Thu" |
| \i 5 = "Fri" |
| \i 6 = "Sat" |
| \i 7 = "Sun" |
| \endlist |
| |
| The day names will be localized according to the system's locale |
| settings. |
| |
| \sa toString(), shortMonthName(), longMonthName(), longDayName() |
| */ |
| |
| QString QDate::shortDayName(int weekday, MonthNameType type) |
| { |
| if (weekday < 1 || weekday > 7) { |
| weekday = 1; |
| } |
| switch (type) { |
| case QDate::DateFormat: |
| return QLocale::system().dayName(weekday, QLocale::ShortFormat); |
| case QDate::StandaloneFormat: |
| return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat); |
| default: |
| break; |
| } |
| return QString(); |
| } |
| |
| /*! |
| Returns the short version of the name of the \a weekday. The |
| returned name is in normal type which can be used for date formatting. |
| |
| \sa toString(), longDayName(), shortMonthName(), longMonthName() |
| */ |
| |
| QString QDate::shortDayName(int weekday) |
| { |
| if (weekday < 1 || weekday > 7) { |
| weekday = 1; |
| } |
| return QLocale::system().dayName(weekday, QLocale::ShortFormat); |
| } |
| |
| /*! |
| \since 4.5 |
| |
| Returns the long name of the \a weekday for the representation specified |
| by \a type. |
| |
| The days are enumerated using the following convention: |
| |
| \list |
| \i 1 = "Monday" |
| \i 2 = "Tuesday" |
| \i 3 = "Wednesday" |
| \i 4 = "Thursday" |
| \i 5 = "Friday" |
| \i 6 = "Saturday" |
| \i 7 = "Sunday" |
| \endlist |
| |
| The day names will be localized according to the system's locale |
| settings. |
| |
| \sa toString(), shortDayName(), shortMonthName(), longMonthName() |
| */ |
| |
| QString QDate::longDayName(int weekday, MonthNameType type) |
| { |
| if (weekday < 1 || weekday > 7) { |
| weekday = 1; |
| } |
| switch (type) { |
| case QDate::DateFormat: |
| return QLocale::system().dayName(weekday, QLocale::LongFormat); |
| case QDate::StandaloneFormat: |
| return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat); |
| default: |
| break; |
| } |
| return QLocale::system().dayName(weekday, QLocale::LongFormat); |
| } |
| |
| /*! |
| Returns the long version of the name of the \a weekday. The |
| returned name is in normal type which can be used for date formatting. |
| |
| \sa toString(), shortDayName(), shortMonthName(), longMonthName() |
| */ |
| |
| QString QDate::longDayName(int weekday) |
| { |
| if (weekday < 1 || weekday > 7) { |
| weekday = 1; |
| } |
| return QLocale::system().dayName(weekday, QLocale::LongFormat); |
| } |
| #endif //QT_NO_TEXTDATE |
| |
| #ifndef QT_NO_DATESTRING |
| |
| /*! |
| \fn QString QDate::toString(Qt::DateFormat format) const |
| |
| \overload |
| |
| Returns the date as a string. The \a format parameter determines |
| the format of the string. |
| |
| If the \a format is Qt::TextDate, the string is formatted in |
| the default way. QDate::shortDayName() and QDate::shortMonthName() |
| are used to generate the string, so the day and month names will |
| be localized names. An example of this formatting is |
| "Sat May 20 1995". |
| |
| If the \a format is Qt::ISODate, the string format corresponds |
| to the ISO 8601 extended specification for representations of |
| dates and times, taking the form YYYY-MM-DD, where YYYY is the |
| year, MM is the month of the year (between 01 and 12), and DD is |
| the day of the month between 01 and 31. |
| |
| If the \a format is Qt::SystemLocaleShortDate or |
| Qt::SystemLocaleLongDate, the string format depends on the locale |
| settings of the system. Identical to calling |
| QLocale::system().toString(date, QLocale::ShortFormat) or |
| QLocale::system().toString(date, QLocale::LongFormat). |
| |
| If the \a format is Qt::DefaultLocaleShortDate or |
| Qt::DefaultLocaleLongDate, the string format depends on the |
| default application locale. This is the locale set with |
| QLocale::setDefault(), or the system locale if no default locale |
| has been set. Identical to calling QLocale().toString(date, |
| QLocale::ShortFormat) or QLocale().toString(date, |
| QLocale::LongFormat). |
| |
| If the date is invalid, an empty string will be returned. |
| |
| \warning The Qt::ISODate format is only valid for years in the |
| range 0 to 9999. This restriction may apply to locale-aware |
| formats as well, depending on the locale settings. |
| |
| \sa shortDayName(), shortMonthName() |
| */ |
| QString QDate::toString(Qt::DateFormat f) const |
| { |
| if (!isValid()) |
| return QString(); |
| int y, m, d; |
| getDateFromJulianDay(jd, &y, &m, &d); |
| switch (f) { |
| case Qt::SystemLocaleDate: |
| case Qt::SystemLocaleShortDate: |
| case Qt::SystemLocaleLongDate: |
| return QLocale::system().toString(*this, f == Qt::SystemLocaleLongDate ? QLocale::LongFormat |
| : QLocale::ShortFormat); |
| case Qt::LocaleDate: |
| case Qt::DefaultLocaleShortDate: |
| case Qt::DefaultLocaleLongDate: |
| return QLocale().toString(*this, f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat |
| : QLocale::ShortFormat); |
| default: |
| #ifndef QT_NO_TEXTDATE |
| case Qt::TextDate: |
| { |
| return QString::fromLatin1("%0 %1 %2 %3") |
| .arg(shortDayName(dayOfWeek())) |
| .arg(shortMonthName(m)) |
| .arg(d) |
| .arg(y); |
| } |
| #endif |
| case Qt::ISODate: |
| { |
| if (year() < 0 || year() > 9999) |
| return QString(); |
| QString month(QString::number(m).rightJustified(2, QLatin1Char('0'))); |
| QString day(QString::number(d).rightJustified(2, QLatin1Char('0'))); |
| return QString::number(y) + QLatin1Char('-') + month + QLatin1Char('-') + day; |
| } |
| } |
| } |
| |
| /*! |
| Returns the date as a string. The \a format parameter determines |
| the format of the result string. |
| |
| These expressions may be used: |
| |
| \table |
| \header \i Expression \i Output |
| \row \i d \i the day as number without a leading zero (1 to 31) |
| \row \i dd \i the day as number with a leading zero (01 to 31) |
| \row \i ddd |
| \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). |
| Uses QDate::shortDayName(). |
| \row \i dddd |
| \i the long localized day name (e.g. 'Monday' to 'Sunday'). |
| Uses QDate::longDayName(). |
| \row \i M \i the month as number without a leading zero (1 to 12) |
| \row \i MM \i the month as number with a leading zero (01 to 12) |
| \row \i MMM |
| \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). |
| Uses QDate::shortMonthName(). |
| \row \i MMMM |
| \i the long localized month name (e.g. 'January' to 'December'). |
| Uses QDate::longMonthName(). |
| \row \i yy \i the year as two digit number (00 to 99) |
| \row \i yyyy \i the year as four digit number. If the year is negative, |
| a minus sign is prepended in addition. |
| \endtable |
| |
| All other input characters will be ignored. Any sequence of characters that |
| are enclosed in singlequotes will be treated as text and not be used as an |
| expression. Two consecutive singlequotes ("''") are replaced by a singlequote |
| in the output. |
| |
| Example format strings (assuming that the QDate is the 20 July |
| 1969): |
| |
| \table |
| \header \o Format \o Result |
| \row \o dd.MM.yyyy \o 20.07.1969 |
| \row \o ddd MMMM d yy \o Sun July 20 69 |
| \row \o 'The day is' dddd \o The day is Sunday |
| \endtable |
| |
| If the datetime is invalid, an empty string will be returned. |
| |
| \warning The Qt::ISODate format is only valid for years in the |
| range 0 to 9999. This restriction may apply to locale-aware |
| formats as well, depending on the locale settings. |
| |
| \sa QDateTime::toString() QTime::toString() |
| |
| */ |
| QString QDate::toString(const QString& format) const |
| { |
| if (year() > 9999) |
| return QString(); |
| return fmtDateTime(format, 0, this); |
| } |
| #endif //QT_NO_DATESTRING |
| |
| /*! |
| \obsolete |
| |
| Sets the date's year \a y, month \a m, and day \a d. |
| |
| If \a y is in the range 0 to 99, it is interpreted as 1900 to |
| 1999. |
| |
| Use setDate() instead. |
| */ |
| |
| bool QDate::setYMD(int y, int m, int d) |
| { |
| if (uint(y) <= 99) |
| y += 1900; |
| return setDate(y, m, d); |
| } |
| |
| /*! |
| \since 4.2 |
| |
| Sets the date's \a year, \a month, and \a day. Returns true if |
| the date is valid; otherwise returns false. |
| |
| If the specified date is invalid, the QDate object is set to be |
| invalid. Any date before 2 January 4713 B.C. is considered |
| invalid. |
| |
| \sa isValid() |
| */ |
| bool QDate::setDate(int year, int month, int day) |
| { |
| if (!isValid(year, month, day)) { |
| jd = 0; |
| } else { |
| jd = julianDayFromDate(year, month, day); |
| } |
| return jd != 0; |
| } |
| |
| /*! |
| \since 4.5 |
| |
| Extracts the date's year, month, and day, and assigns them to |
| *\a year, *\a month, and *\a day. The pointers may be null. |
| |
| \sa year(), month(), day(), isValid() |
| */ |
| void QDate::getDate(int *year, int *month, int *day) |
| { |
| getDateFromJulianDay(jd, year, month, day); |
| } |
| |
| /*! |
| Returns a QDate object containing a date \a ndays later than the |
| date of this object (or earlier if \a ndays is negative). |
| |
| \sa addMonths() addYears() daysTo() |
| */ |
| |
| QDate QDate::addDays(int ndays) const |
| { |
| QDate d; |
| // this is basically "d.jd = jd + ndays" with checks for integer overflow |
| if (ndays >= 0) |
| d.jd = (jd + ndays >= jd) ? jd + ndays : 0; |
| else |
| d.jd = (jd + ndays < jd) ? jd + ndays : 0; |
| return d; |
| } |
| |
| /*! |
| Returns a QDate object containing a date \a nmonths later than the |
| date of this object (or earlier if \a nmonths is negative). |
| |
| \note If the ending day/month combination does not exist in the |
| resulting month/year, this function will return a date that is the |
| latest valid date. |
| |
| \warning QDate has a date hole around the days introducing the |
| Gregorian calendar (the days 5 to 14 October 1582, inclusive, do |
| not exist). If the calculation ends in one of those days, QDate |
| will return either October 4 or October 15. |
| |
| \sa addDays() addYears() |
| */ |
| |
| QDate QDate::addMonths(int nmonths) const |
| { |
| if (!isValid()) |
| return QDate(); |
| if (!nmonths) |
| return *this; |
| |
| int old_y, y, m, d; |
| getDateFromJulianDay(jd, &y, &m, &d); |
| old_y = y; |
| |
| bool increasing = nmonths > 0; |
| |
| while (nmonths != 0) { |
| if (nmonths < 0 && nmonths + 12 <= 0) { |
| y--; |
| nmonths+=12; |
| } else if (nmonths < 0) { |
| m+= nmonths; |
| nmonths = 0; |
| if (m <= 0) { |
| --y; |
| m += 12; |
| } |
| } else if (nmonths - 12 >= 0) { |
| y++; |
| nmonths -= 12; |
| } else if (m == 12) { |
| y++; |
| m = 0; |
| } else { |
| m += nmonths; |
| nmonths = 0; |
| if (m > 12) { |
| ++y; |
| m -= 12; |
| } |
| } |
| } |
| |
| // was there a sign change? |
| if ((old_y > 0 && y <= 0) || |
| (old_y < 0 && y >= 0)) |
| // yes, adjust the date by +1 or -1 years |
| y += increasing ? +1 : -1; |
| |
| // did we end up in the Gregorian/Julian conversion hole? |
| if (y == 1582 && m == 10 && d > 4 && d < 15) |
| d = increasing ? 15 : 4; |
| |
| return fixedDate(y, m, d); |
| } |
| |
| /*! |
| Returns a QDate object containing a date \a nyears later than the |
| date of this object (or earlier if \a nyears is negative). |
| |
| \note If the ending day/month combination does not exist in the |
| resulting year (i.e., if the date was Feb 29 and the final year is |
| not a leap year), this function will return a date that is the |
| latest valid date (that is, Feb 28). |
| |
| \sa addDays(), addMonths() |
| */ |
| |
| QDate QDate::addYears(int nyears) const |
| { |
| if (!isValid()) |
| return QDate(); |
| |
| int y, m, d; |
| getDateFromJulianDay(jd, &y, &m, &d); |
| |
| int old_y = y; |
| y += nyears; |
| |
| // was there a sign change? |
| if ((old_y > 0 && y <= 0) || |
| (old_y < 0 && y >= 0)) |
| // yes, adjust the date by +1 or -1 years |
| y += nyears > 0 ? +1 : -1; |
| |
| return fixedDate(y, m, d); |
| } |
| |
| /*! |
| Returns the number of days from this date to \a d (which is |
| negative if \a d is earlier than this date). |
| |
| Example: |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 0 |
| |
| \sa addDays() |
| */ |
| |
| int QDate::daysTo(const QDate &d) const |
| { |
| return d.jd - jd; |
| } |
| |
| |
| /*! |
| \fn bool QDate::operator==(const QDate &d) const |
| |
| Returns true if this date is equal to \a d; otherwise returns |
| false. |
| |
| */ |
| |
| /*! |
| \fn bool QDate::operator!=(const QDate &d) const |
| |
| Returns true if this date is different from \a d; otherwise |
| returns false. |
| */ |
| |
| /*! |
| \fn bool QDate::operator<(const QDate &d) const |
| |
| Returns true if this date is earlier than \a d; otherwise returns |
| false. |
| */ |
| |
| /*! |
| \fn bool QDate::operator<=(const QDate &d) const |
| |
| Returns true if this date is earlier than or equal to \a d; |
| otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QDate::operator>(const QDate &d) const |
| |
| Returns true if this date is later than \a d; otherwise returns |
| false. |
| */ |
| |
| /*! |
| \fn bool QDate::operator>=(const QDate &d) const |
| |
| Returns true if this date is later than or equal to \a d; |
| otherwise returns false. |
| */ |
| |
| /*! |
| \fn QDate::currentDate() |
| Returns the current date, as reported by the system clock. |
| |
| \sa QTime::currentTime(), QDateTime::currentDateTime() |
| */ |
| |
| #ifndef QT_NO_DATESTRING |
| /*! |
| \fn QDate QDate::fromString(const QString &string, Qt::DateFormat format) |
| |
| Returns the QDate represented by the \a string, using the |
| \a format given, or an invalid date if the string cannot be |
| parsed. |
| |
| Note for Qt::TextDate: It is recommended that you use the |
| English short month names (e.g. "Jan"). Although localized month |
| names can also be used, they depend on the user's locale settings. |
| */ |
| QDate QDate::fromString(const QString& s, Qt::DateFormat f) |
| { |
| if (s.isEmpty()) |
| return QDate(); |
| |
| switch (f) { |
| case Qt::ISODate: |
| { |
| int year(s.mid(0, 4).toInt()); |
| int month(s.mid(5, 2).toInt()); |
| int day(s.mid(8, 2).toInt()); |
| if (year && month && day) |
| return QDate(year, month, day); |
| } |
| break; |
| case Qt::SystemLocaleDate: |
| case Qt::SystemLocaleShortDate: |
| case Qt::SystemLocaleLongDate: |
| return fromString(s, QLocale::system().dateFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat |
| : QLocale::ShortFormat)); |
| case Qt::LocaleDate: |
| case Qt::DefaultLocaleShortDate: |
| case Qt::DefaultLocaleLongDate: |
| return fromString(s, QLocale().dateFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat |
| : QLocale::ShortFormat)); |
| default: |
| #ifndef QT_NO_TEXTDATE |
| case Qt::TextDate: { |
| QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts); |
| |
| if (parts.count() != 4) { |
| return QDate(); |
| } |
| |
| QString monthName = parts.at(1); |
| int month = -1; |
| // Assume that English monthnames are the default |
| for (int i = 0; i < 12; ++i) { |
| if (monthName == QLatin1String(qt_shortMonthNames[i])) { |
| month = i + 1; |
| break; |
| } |
| } |
| // If English names can't be found, search the localized ones |
| if (month == -1) { |
| for (int i = 1; i <= 12; ++i) { |
| if (monthName == QDate::shortMonthName(i)) { |
| month = i; |
| break; |
| } |
| } |
| } |
| if (month < 1 || month > 12) { |
| return QDate(); |
| } |
| |
| bool ok; |
| int day = parts.at(2).toInt(&ok); |
| if (!ok) { |
| return QDate(); |
| } |
| |
| int year = parts.at(3).toInt(&ok); |
| if (!ok) { |
| return QDate(); |
| } |
| |
| return QDate(year, month, day); |
| } |
| #else |
| break; |
| #endif |
| } |
| return QDate(); |
| } |
| |
| /*! |
| \fn QDate::fromString(const QString &string, const QString &format) |
| |
| Returns the QDate represented by the \a string, using the \a |
| format given, or an invalid date if the string cannot be parsed. |
| |
| These expressions may be used for the format: |
| |
| \table |
| \header \i Expression \i Output |
| \row \i d \i The day as a number without a leading zero (1 to 31) |
| \row \i dd \i The day as a number with a leading zero (01 to 31) |
| \row \i ddd |
| \i The abbreviated localized day name (e.g. 'Mon' to 'Sun'). |
| Uses QDate::shortDayName(). |
| \row \i dddd |
| \i The long localized day name (e.g. 'Monday' to 'Sunday'). |
| Uses QDate::longDayName(). |
| \row \i M \i The month as a number without a leading zero (1 to 12) |
| \row \i MM \i The month as a number with a leading zero (01 to 12) |
| \row \i MMM |
| \i The abbreviated localized month name (e.g. 'Jan' to 'Dec'). |
| Uses QDate::shortMonthName(). |
| \row \i MMMM |
| \i The long localized month name (e.g. 'January' to 'December'). |
| Uses QDate::longMonthName(). |
| \row \i yy \i The year as two digit number (00 to 99) |
| \row \i yyyy \i The year as four digit number. If the year is negative, |
| a minus sign is prepended in addition. |
| \endtable |
| |
| All other input characters will be treated as text. Any sequence |
| of characters that are enclosed in single quotes will also be |
| treated as text and will not be used as an expression. For example: |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 1 |
| |
| If the format is not satisfied, an invalid QDate is returned. The |
| expressions that don't expect leading zeroes (d, M) will be |
| greedy. This means that they will use two digits even if this |
| will put them outside the accepted range of values and leaves too |
| few digits for other sections. For example, the following format |
| string could have meant January 30 but the M will grab two |
| digits, resulting in an invalid date: |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 2 |
| |
| For any field that is not represented in the format the following |
| defaults are used: |
| |
| \table |
| \header \i Field \i Default value |
| \row \i Year \i 1900 |
| \row \i Month \i 1 |
| \row \i Day \i 1 |
| \endtable |
| |
| The following examples demonstrate the default values: |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 3 |
| |
| \sa QDateTime::fromString(), QTime::fromString(), QDate::toString(), |
| QDateTime::toString(), QTime::toString() |
| */ |
| |
| QDate QDate::fromString(const QString &string, const QString &format) |
| { |
| QDate date; |
| #ifndef QT_BOOTSTRAPPED |
| QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString); |
| if (dt.parseFormat(format)) |
| dt.fromString(string, &date, 0); |
| #else |
| Q_UNUSED(string); |
| Q_UNUSED(format); |
| #endif |
| return date; |
| } |
| #endif // QT_NO_DATESTRING |
| |
| /*! |
| \overload |
| |
| Returns true if the specified date (\a year, \a month, and \a |
| day) is valid; otherwise returns false. |
| |
| Example: |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 4 |
| |
| \sa isNull(), setDate() |
| */ |
| |
| bool QDate::isValid(int year, int month, int day) |
| { |
| if (year < FIRST_YEAR |
| || (year == FIRST_YEAR && |
| (month < FIRST_MONTH |
| || (month == FIRST_MONTH && day < FIRST_DAY))) |
| || year == 0) // there is no year 0 in the Julian calendar |
| return false; |
| |
| // passage from Julian to Gregorian calendar |
| if (year == 1582 && month == 10 && day > 4 && day < 15) |
| return 0; |
| |
| return (day > 0 && month > 0 && month <= 12) && |
| (day <= monthDays[month] || (day == 29 && month == 2 && isLeapYear(year))); |
| } |
| |
| /*! |
| \fn bool QDate::isLeapYear(int year) |
| |
| Returns true if the specified \a year is a leap year; otherwise |
| returns false. |
| */ |
| |
| bool QDate::isLeapYear(int y) |
| { |
| if (y < 1582) { |
| if ( y < 1) { // No year 0 in Julian calendar, so -1, -5, -9 etc are leap years |
| ++y; |
| } |
| return y % 4 == 0; |
| } else { |
| return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0; |
| } |
| } |
| |
| /*! |
| \internal |
| |
| This function has a confusing name and shouldn't be part of the |
| API anyway, since we have toJulian() and fromJulian(). |
| ### Qt 5: remove it |
| */ |
| uint QDate::gregorianToJulian(int y, int m, int d) |
| { |
| return julianDayFromDate(y, m, d); |
| } |
| |
| /*! |
| \internal |
| |
| This function has a confusing name and shouldn't be part of the |
| API anyway, since we have toJulian() and fromJulian(). |
| ### Qt 5: remove it |
| */ |
| void QDate::julianToGregorian(uint jd, int &y, int &m, int &d) |
| { |
| getDateFromJulianDay(jd, &y, &m, &d); |
| } |
| |
| /*! \fn static QDate QDate::fromJulianDay(int jd) |
| |
| Converts the Julian day \a jd to a QDate. |
| |
| \sa toJulianDay() |
| */ |
| |
| /*! \fn int QDate::toJulianDay() const |
| |
| Converts the date to a Julian day. |
| |
| \sa fromJulianDay() |
| */ |
| |
| /***************************************************************************** |
| QTime member functions |
| *****************************************************************************/ |
| |
| /*! |
| \class QTime |
| \reentrant |
| |
| \brief The QTime class provides clock time functions. |
| |
| |
| A QTime object contains a clock time, i.e. the number of hours, |
| minutes, seconds, and milliseconds since midnight. It can read the |
| current time from the system clock and measure a span of elapsed |
| time. It provides functions for comparing times and for |
| manipulating a time by adding a number of milliseconds. |
| |
| QTime uses the 24-hour clock format; it has no concept of AM/PM. |
| Unlike QDateTime, QTime knows nothing about time zones or |
| daylight savings time (DST). |
| |
| A QTime object is typically created either by giving the number |
| of hours, minutes, seconds, and milliseconds explicitly, or by |
| using the static function currentTime(), which creates a QTime |
| object that contains the system's local time. Note that the |
| accuracy depends on the accuracy of the underlying operating |
| system; not all systems provide 1-millisecond accuracy. |
| |
| The hour(), minute(), second(), and msec() functions provide |
| access to the number of hours, minutes, seconds, and milliseconds |
| of the time. The same information is provided in textual format by |
| the toString() function. |
| |
| QTime provides a full set of operators to compare two QTime |
| objects. One time is considered smaller than another if it is |
| earlier than the other. |
| |
| The time a given number of seconds or milliseconds later than a |
| given time can be found using the addSecs() or addMSecs() |
| functions. Correspondingly, the number of seconds or milliseconds |
| between two times can be found using secsTo() or msecsTo(). |
| |
| QTime can be used to measure a span of elapsed time using the |
| start(), restart(), and elapsed() functions. |
| |
| \sa QDate, QDateTime |
| */ |
| |
| /*! |
| \fn QTime::QTime() |
| |
| Constructs a null time object. A null time can be a QTime(0, 0, 0, 0) |
| (i.e., midnight) object, except that isNull() returns true and isValid() |
| returns false. |
| |
| \sa isNull(), isValid() |
| */ |
| |
| /*! |
| Constructs a time with hour \a h, minute \a m, seconds \a s and |
| milliseconds \a ms. |
| |
| \a h must be in the range 0 to 23, \a m and \a s must be in the |
| range 0 to 59, and \a ms must be in the range 0 to 999. |
| |
| \sa isValid() |
| */ |
| |
| QTime::QTime(int h, int m, int s, int ms) |
| { |
| setHMS(h, m, s, ms); |
| } |
| |
| |
| /*! |
| \fn bool QTime::isNull() const |
| |
| Returns true if the time is null (i.e., the QTime object was |
| constructed using the default constructor); otherwise returns |
| false. A null time is also an invalid time. |
| |
| \sa isValid() |
| */ |
| |
| /*! |
| Returns true if the time is valid; otherwise returns false. For example, |
| the time 23:30:55.746 is valid, but 24:12:30 is invalid. |
| |
| \sa isNull() |
| */ |
| |
| bool QTime::isValid() const |
| { |
| return mds > NullTime && mds < MSECS_PER_DAY; |
| } |
| |
| |
| /*! |
| Returns the hour part (0 to 23) of the time. |
| |
| \sa minute(), second(), msec() |
| */ |
| |
| int QTime::hour() const |
| { |
| return ds() / MSECS_PER_HOUR; |
| } |
| |
| /*! |
| Returns the minute part (0 to 59) of the time. |
| |
| \sa hour(), second(), msec() |
| */ |
| |
| int QTime::minute() const |
| { |
| return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN; |
| } |
| |
| /*! |
| Returns the second part (0 to 59) of the time. |
| |
| \sa hour(), minute(), msec() |
| */ |
| |
| int QTime::second() const |
| { |
| return (ds() / 1000)%SECS_PER_MIN; |
| } |
| |
| /*! |
| Returns the millisecond part (0 to 999) of the time. |
| |
| \sa hour(), minute(), second() |
| */ |
| |
| int QTime::msec() const |
| { |
| return ds() % 1000; |
| } |
| |
| #ifndef QT_NO_DATESTRING |
| /*! |
| \overload |
| |
| Returns the time as a string. Milliseconds are not included. The |
| \a format parameter determines the format of the string. |
| |
| If \a format is Qt::TextDate, the string format is HH:MM:SS; e.g. 1 |
| second before midnight would be "23:59:59". |
| |
| If \a format is Qt::ISODate, the string format corresponds to the |
| ISO 8601 extended specification for representations of dates, |
| which is also HH:MM:SS. (However, contrary to ISO 8601, dates |
| before 15 October 1582 are handled as Julian dates, not Gregorian |
| dates. See \l{QDate G and J} {Use of Gregorian and Julian |
| Calendars}. This might change in a future version of Qt.) |
| |
| If the \a format is Qt::SystemLocaleShortDate or |
| Qt::SystemLocaleLongDate, the string format depends on the locale |
| settings of the system. Identical to calling |
| QLocale::system().toString(time, QLocale::ShortFormat) or |
| QLocale::system().toString(time, QLocale::LongFormat). |
| |
| If the \a format is Qt::DefaultLocaleShortDate or |
| Qt::DefaultLocaleLongDate, the string format depends on the |
| default application locale. This is the locale set with |
| QLocale::setDefault(), or the system locale if no default locale |
| has been set. Identical to calling QLocale().toString(time, |
| QLocale::ShortFormat) or QLocale().toString(time, |
| QLocale::LongFormat). |
| |
| If the time is invalid, an empty string will be returned. |
| */ |
| |
| QString QTime::toString(Qt::DateFormat format) const |
| { |
| if (!isValid()) |
| return QString(); |
| |
| switch (format) { |
| case Qt::SystemLocaleDate: |
| case Qt::SystemLocaleShortDate: |
| case Qt::SystemLocaleLongDate: |
| return QLocale::system().toString(*this, format == Qt::SystemLocaleLongDate ? QLocale::LongFormat |
| : QLocale::ShortFormat); |
| case Qt::LocaleDate: |
| case Qt::DefaultLocaleShortDate: |
| case Qt::DefaultLocaleLongDate: |
| return QLocale().toString(*this, format == Qt::DefaultLocaleLongDate ? QLocale::LongFormat |
| : QLocale::ShortFormat); |
| |
| default: |
| case Qt::ISODate: |
| case Qt::TextDate: |
| return QString::fromLatin1("%1:%2:%3") |
| .arg(hour(), 2, 10, QLatin1Char('0')) |
| .arg(minute(), 2, 10, QLatin1Char('0')) |
| .arg(second(), 2, 10, QLatin1Char('0')); |
| } |
| } |
| |
| /*! |
| Returns the time as a string. The \a format parameter determines |
| the format of the result string. |
| |
| These expressions may be used: |
| |
| \table |
| \header \i Expression \i Output |
| \row \i h |
| \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) |
| \row \i hh |
| \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) |
| \row \i H |
| \i the hour without a leading zero (0 to 23, even with AM/PM display) |
| \row \i HH |
| \i the hour with a leading zero (00 to 23, even with AM/PM display) |
| \row \i m \i the minute without a leading zero (0 to 59) |
| \row \i mm \i the minute with a leading zero (00 to 59) |
| \row \i s \i the second without a leading zero (0 to 59) |
| \row \i ss \i the second with a leading zero (00 to 59) |
| \row \i z \i the milliseconds without leading zeroes (0 to 999) |
| \row \i zzz \i the milliseconds with leading zeroes (000 to 999) |
| \row \i AP or A |
| \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". |
| \row \i ap or a |
| \i use am/pm display. \e ap will be replaced by either "am" or "pm". |
| \row \i t \i the timezone (for example "CEST") |
| \endtable |
| |
| All other input characters will be ignored. Any sequence of characters that |
| are enclosed in singlequotes will be treated as text and not be used as an |
| expression. Two consecutive singlequotes ("''") are replaced by a singlequote |
| in the output. |
| |
| Example format strings (assuming that the QTime is 14:13:09.042) |
| |
| \table |
| \header \i Format \i Result |
| \row \i hh:mm:ss.zzz \i 14:13:09.042 |
| \row \i h:m:s ap \i 2:13:9 pm |
| \row \i H:m:s a \i 14:13:9 pm |
| \endtable |
| |
| If the datetime is invalid, an empty string will be returned. |
| If \a format is empty, the default format "hh:mm:ss" is used. |
| |
| \sa QDate::toString() QDateTime::toString() |
| */ |
| QString QTime::toString(const QString& format) const |
| { |
| return fmtDateTime(format, this, 0); |
| } |
| #endif //QT_NO_DATESTRING |
| /*! |
| Sets the time to hour \a h, minute \a m, seconds \a s and |
| milliseconds \a ms. |
| |
| \a h must be in the range 0 to 23, \a m and \a s must be in the |
| range 0 to 59, and \a ms must be in the range 0 to 999. |
| Returns true if the set time is valid; otherwise returns false. |
| |
| \sa isValid() |
| */ |
| |
| bool QTime::setHMS(int h, int m, int s, int ms) |
| { |
| #if defined(Q_OS_WINCE) |
| startTick = NullTime; |
| #endif |
| if (!isValid(h,m,s,ms)) { |
| mds = NullTime; // make this invalid |
| return false; |
| } |
| mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms; |
| return true; |
| } |
| |
| /*! |
| Returns a QTime object containing a time \a s seconds later |
| than the time of this object (or earlier if \a s is negative). |
| |
| Note that the time will wrap if it passes midnight. |
| |
| Example: |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 5 |
| |
| \sa addMSecs(), secsTo(), QDateTime::addSecs() |
| */ |
| |
| QTime QTime::addSecs(int s) const |
| { |
| return addMSecs(s * 1000); |
| } |
| |
| /*! |
| Returns the number of seconds from this time to \a t. |
| If \a t is earlier than this time, the number of seconds returned |
| is negative. |
| |
| Because QTime measures time within a day and there are 86400 |
| seconds in a day, the result is always between -86400 and 86400. |
| |
| secsTo() does not take into account any milliseconds. |
| |
| \sa addSecs(), QDateTime::secsTo() |
| */ |
| |
| int QTime::secsTo(const QTime &t) const |
| { |
| return (t.ds() - ds()) / 1000; |
| } |
| |
| /*! |
| Returns a QTime object containing a time \a ms milliseconds later |
| than the time of this object (or earlier if \a ms is negative). |
| |
| Note that the time will wrap if it passes midnight. See addSecs() |
| for an example. |
| |
| \sa addSecs(), msecsTo(), QDateTime::addMSecs() |
| */ |
| |
| QTime QTime::addMSecs(int ms) const |
| { |
| QTime t; |
| if (ms < 0) { |
| // % not well-defined for -ve, but / is. |
| int negdays = (MSECS_PER_DAY - ms) / MSECS_PER_DAY; |
| t.mds = (ds() + ms + negdays * MSECS_PER_DAY) % MSECS_PER_DAY; |
| } else { |
| t.mds = (ds() + ms) % MSECS_PER_DAY; |
| } |
| #if defined(Q_OS_WINCE) |
| if (startTick > NullTime) |
| t.startTick = (startTick + ms) % MSECS_PER_DAY; |
| #endif |
| return t; |
| } |
| |
| /*! |
| Returns the number of milliseconds from this time to \a t. |
| If \a t is earlier than this time, the number of milliseconds returned |
| is negative. |
| |
| Because QTime measures time within a day and there are 86400 |
| seconds in a day, the result is always between -86400000 and |
| 86400000 ms. |
| |
| \sa secsTo(), addMSecs(), QDateTime::msecsTo() |
| */ |
| |
| int QTime::msecsTo(const QTime &t) const |
| { |
| #if defined(Q_OS_WINCE) |
| // GetLocalTime() for Windows CE has no milliseconds resolution |
| if (t.startTick > NullTime && startTick > NullTime) |
| return t.startTick - startTick; |
| else |
| #endif |
| return t.ds() - ds(); |
| } |
| |
| |
| /*! |
| \fn bool QTime::operator==(const QTime &t) const |
| |
| Returns true if this time is equal to \a t; otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QTime::operator!=(const QTime &t) const |
| |
| Returns true if this time is different from \a t; otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QTime::operator<(const QTime &t) const |
| |
| Returns true if this time is earlier than \a t; otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QTime::operator<=(const QTime &t) const |
| |
| Returns true if this time is earlier than or equal to \a t; |
| otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QTime::operator>(const QTime &t) const |
| |
| Returns true if this time is later than \a t; otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QTime::operator>=(const QTime &t) const |
| |
| Returns true if this time is later than or equal to \a t; |
| otherwise returns false. |
| */ |
| |
| /*! |
| \fn QTime::currentTime() |
| |
| Returns the current time as reported by the system clock. |
| |
| Note that the accuracy depends on the accuracy of the underlying |
| operating system; not all systems provide 1-millisecond accuracy. |
| */ |
| |
| #ifndef QT_NO_DATESTRING |
| /*! |
| \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format) |
| |
| Returns the time represented in the \a string as a QTime using the |
| \a format given, or an invalid time if this is not possible. |
| |
| Note that fromString() uses a "C" locale encoded string to convert |
| milliseconds to a float value. If the default locale is not "C", |
| this may result in two conversion attempts (if the conversion |
| fails for the default locale). This should be considered an |
| implementation detail. |
| */ |
| QTime QTime::fromString(const QString& s, Qt::DateFormat f) |
| { |
| if (s.isEmpty()) { |
| QTime t; |
| t.mds = NullTime; |
| return t; |
| } |
| |
| switch (f) { |
| case Qt::SystemLocaleDate: |
| case Qt::SystemLocaleShortDate: |
| case Qt::SystemLocaleLongDate: |
| return fromString(s, QLocale::system().timeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat |
| : QLocale::ShortFormat)); |
| case Qt::LocaleDate: |
| case Qt::DefaultLocaleShortDate: |
| case Qt::DefaultLocaleLongDate: |
| return fromString(s, QLocale().timeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat |
| : QLocale::ShortFormat)); |
| default: |
| { |
| bool ok = true; |
| const int hour(s.mid(0, 2).toInt(&ok)); |
| if (!ok) |
| return QTime(); |
| const int minute(s.mid(3, 2).toInt(&ok)); |
| if (!ok) |
| return QTime(); |
| const int second(s.mid(6, 2).toInt(&ok)); |
| if (!ok) |
| return QTime(); |
| const QString msec_s(QLatin1String("0.") + s.mid(9, 4)); |
| const float msec(msec_s.toFloat(&ok)); |
| if (!ok) |
| return QTime(hour, minute, second, 0); |
| return QTime(hour, minute, second, qMin(qRound(msec * 1000.0), 999)); |
| } |
| } |
| } |
| |
| /*! |
| \fn QTime::fromString(const QString &string, const QString &format) |
| |
| Returns the QTime represented by the \a string, using the \a |
| format given, or an invalid time if the string cannot be parsed. |
| |
| These expressions may be used for the format: |
| |
| \table |
| \header \i Expression \i Output |
| \row \i h |
| \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) |
| \row \i hh |
| \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) |
| \row \i m \i the minute without a leading zero (0 to 59) |
| \row \i mm \i the minute with a leading zero (00 to 59) |
| \row \i s \i the second without a leading zero (0 to 59) |
| \row \i ss \i the second with a leading zero (00 to 59) |
| \row \i z \i the milliseconds without leading zeroes (0 to 999) |
| \row \i zzz \i the milliseconds with leading zeroes (000 to 999) |
| \row \i AP |
| \i interpret as an AM/PM time. \e AP must be either "AM" or "PM". |
| \row \i ap |
| \i Interpret as an AM/PM time. \e ap must be either "am" or "pm". |
| \endtable |
| |
| All other input characters will be treated as text. Any sequence |
| of characters that are enclosed in single quotes will also be |
| treated as text and not be used as an expression. |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 6 |
| |
| If the format is not satisfied an invalid QTime is returned. |
| Expressions that do not expect leading zeroes to be given (h, m, s |
| and z) are greedy. This means that they will use two digits even if |
| this puts them outside the range of accepted values and leaves too |
| few digits for other sections. For example, the following string |
| could have meant 00:07:10, but the m will grab two digits, resulting |
| in an invalid time: |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 7 |
| |
| Any field that is not represented in the format will be set to zero. |
| For example: |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 8 |
| |
| \sa QDateTime::fromString() QDate::fromString() QDate::toString() |
| QDateTime::toString() QTime::toString() |
| */ |
| |
| QTime QTime::fromString(const QString &string, const QString &format) |
| { |
| QTime time; |
| #ifndef QT_BOOTSTRAPPED |
| QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString); |
| if (dt.parseFormat(format)) |
| dt.fromString(string, 0, &time); |
| #else |
| Q_UNUSED(string); |
| Q_UNUSED(format); |
| #endif |
| return time; |
| } |
| |
| #endif // QT_NO_DATESTRING |
| |
| |
| /*! |
| \overload |
| |
| Returns true if the specified time is valid; otherwise returns |
| false. |
| |
| The time is valid if \a h is in the range 0 to 23, \a m and |
| \a s are in the range 0 to 59, and \a ms is in the range 0 to 999. |
| |
| Example: |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 9 |
| */ |
| |
| bool QTime::isValid(int h, int m, int s, int ms) |
| { |
| return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000; |
| } |
| |
| |
| /*! |
| Sets this time to the current time. This is practical for timing: |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 10 |
| |
| \sa restart(), elapsed(), currentTime() |
| */ |
| |
| void QTime::start() |
| { |
| *this = currentTime(); |
| } |
| |
| /*! |
| Sets this time to the current time and returns the number of |
| milliseconds that have elapsed since the last time start() or |
| restart() was called. |
| |
| This function is guaranteed to be atomic and is thus very handy |
| for repeated measurements. Call start() to start the first |
| measurement, and restart() for each later measurement. |
| |
| Note that the counter wraps to zero 24 hours after the last call |
| to start() or restart(). |
| |
| \warning If the system's clock setting has been changed since the |
| last time start() or restart() was called, the result is |
| undefined. This can happen when daylight savings time is turned on |
| or off. |
| |
| \sa start(), elapsed(), currentTime() |
| */ |
| |
| int QTime::restart() |
| { |
| QTime t = currentTime(); |
| int n = msecsTo(t); |
| if (n < 0) // passed midnight |
| n += 86400*1000; |
| *this = t; |
| return n; |
| } |
| |
| /*! |
| Returns the number of milliseconds that have elapsed since the |
| last time start() or restart() was called. |
| |
| Note that the counter wraps to zero 24 hours after the last call |
| to start() or restart. |
| |
| Note that the accuracy depends on the accuracy of the underlying |
| operating system; not all systems provide 1-millisecond accuracy. |
| |
| \warning If the system's clock setting has been changed since the |
| last time start() or restart() was called, the result is |
| undefined. This can happen when daylight savings time is turned on |
| or off. |
| |
| \sa start(), restart() |
| */ |
| |
| int QTime::elapsed() const |
| { |
| int n = msecsTo(currentTime()); |
| if (n < 0) // passed midnight |
| n += 86400 * 1000; |
| return n; |
| } |
| |
| |
| /***************************************************************************** |
| QDateTime member functions |
| *****************************************************************************/ |
| |
| /*! |
| \class QDateTime |
| \reentrant |
| \brief The QDateTime class provides date and time functions. |
| |
| |
| A QDateTime object contains a calendar date and a clock time (a |
| "datetime"). It is a combination of the QDate and QTime classes. |
| It can read the current datetime from the system clock. It |
| provides functions for comparing datetimes and for manipulating a |
| datetime by adding a number of seconds, days, months, or years. |
| |
| A QDateTime object is typically created either by giving a date |
| and time explicitly in the constructor, or by using the static |
| function currentDateTime() that returns a QDateTime object set |
| to the system clock's time. The date and time can be changed with |
| setDate() and setTime(). A datetime can also be set using the |
| setTime_t() function that takes a POSIX-standard "number of |
| seconds since 00:00:00 on January 1, 1970" value. The fromString() |
| function returns a QDateTime, given a string and a date format |
| used to interpret the date within the string. |
| |
| The date() and time() functions provide access to the date and |
| time parts of the datetime. The same information is provided in |
| textual format by the toString() function. |
| |
| QDateTime provides a full set of operators to compare two |
| QDateTime objects where smaller means earlier and larger means |
| later. |
| |
| You can increment (or decrement) a datetime by a given number of |
| milliseconds using addMSecs(), seconds using addSecs(), or days |
| using addDays(). Similarly you can use addMonths() and addYears(). |
| The daysTo() function returns the number of days between two datetimes, |
| secsTo() returns the number of seconds between two datetimes, and |
| msecsTo() returns the number of milliseconds between two datetimes. |
| |
| QDateTime can store datetimes as \l{Qt::LocalTime}{local time} or |
| as \l{Qt::UTC}{UTC}. QDateTime::currentDateTime() returns a |
| QDateTime expressed as local time; use toUTC() to convert it to |
| UTC. You can also use timeSpec() to find out if a QDateTime |
| object stores a UTC time or a local time. Operations such as |
| addSecs() and secsTo() are aware of daylight saving time (DST). |
| |
| \note QDateTime does not account for leap seconds. |
| |
| \section1 |
| |
| \target QDateTime G and J |
| \section2 Use of Gregorian and Julian Calendars |
| |
| QDate uses the Gregorian calendar in all locales, beginning |
| on the date 15 October 1582. For dates up to and including 4 |
| October 1582, the Julian calendar is used. This means there is a |
| 10-day gap in the internal calendar between the 4th and the 15th |
| of October 1582. When you use QDateTime for dates in that epoch, |
| the day after 4 October 1582 is 15 October 1582, and the dates in |
| the gap are invalid. |
| |
| The Julian to Gregorian changeover date used here is the date when |
| the Gregorian calendar was first introduced, by Pope Gregory |
| XIII. That change was not universally accepted and some localities |
| only executed it at a later date (if at all). QDateTime |
| doesn't take any of these historical facts into account. If an |
| application must support a locale-specific dating system, it must |
| do so on its own, remembering to convert the dates using the |
| Julian day. |
| |
| \section2 No Year 0 |
| |
| There is no year 0. Dates in that year are considered invalid. The |
| year -1 is the year "1 before Christ" or "1 before current era." |
| The day before 0001-01-01 is December 31st, 1 BCE. |
| |
| \section2 Range of Valid Dates |
| |
| The range of valid dates is from January 2nd, 4713 BCE, to |
| sometime in the year 11 million CE. The Julian Day returned by |
| QDate::toJulianDay() is a number in the contiguous range from 1 to |
| \e{overflow}, even across QDateTime's "date holes". It is suitable |
| for use in applications that must convert a QDateTime to a date in |
| another calendar system, e.g., Hebrew, Islamic or Chinese. |
| |
| The Gregorian calendar was introduced in different places around |
| the world on different dates. QDateTime uses QDate to store the |
| date, so it uses the Gregorian calendar for all locales, beginning |
| on the date 15 October 1582. For dates up to and including 4 |
| October 1582, QDateTime uses the Julian calendar. This means |
| there is a 10-day gap in the QDateTime calendar between the 4th |
| and the 15th of October 1582. When you use QDateTime for dates in |
| that epoch, the day after 4 October 1582 is 15 October 1582, and |
| the dates in the gap are invalid. |
| |
| \section2 |
| Use of System Timezone |
| |
| QDateTime uses the system's time zone information to determine the |
| offset of local time from UTC. If the system is not configured |
| correctly or not up-to-date, QDateTime will give wrong results as |
| well. |
| |
| \section2 Daylight Savings Time (DST) |
| |
| QDateTime takes into account the system's time zone information |
| when dealing with DST. On modern Unix systems, this means it |
| applies the correct historical DST data whenever possible. On |
| Windows and Windows CE, where the system doesn't support |
| historical DST data, historical accuracy is not maintained with |
| respect to DST. |
| |
| The range of valid dates taking DST into account is 1970-01-01 to |
| the present, and rules are in place for handling DST correctly |
| until 2037-12-31, but these could change. For dates falling |
| outside that range, QDateTime makes a \e{best guess} using the |
| rules for year 1970 or 2037, but we can't guarantee accuracy. This |
| means QDateTime doesn't take into account changes in a locale's |
| time zone before 1970, even if the system's time zone database |
| supports that information. |
| |
| \sa QDate QTime QDateTimeEdit |
| */ |
| |
| /*! |
| Constructs a null datetime (i.e. null date and null time). A null |
| datetime is invalid, since the date is invalid. |
| |
| \sa isValid() |
| */ |
| QDateTime::QDateTime() |
| : d(new QDateTimePrivate) |
| { |
| } |
| |
| |
| /*! |
| Constructs a datetime with the given \a date, a valid |
| time(00:00:00.000), and sets the timeSpec() to Qt::LocalTime. |
| */ |
| |
| QDateTime::QDateTime(const QDate &date) |
| : d(new QDateTimePrivate) |
| { |
| d->date = date; |
| d->time = QTime(0, 0, 0); |
| } |
| |
| /*! |
| Constructs a datetime with the given \a date and \a time, using |
| the time specification defined by \a spec. |
| |
| If \a date is valid and \a time is not, the time will be set to midnight. |
| */ |
| |
| QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec) |
| : d(new QDateTimePrivate) |
| { |
| d->date = date; |
| d->time = date.isValid() && !time.isValid() ? QTime(0, 0, 0) : time; |
| d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown; |
| } |
| |
| /*! |
| Constructs a copy of the \a other datetime. |
| */ |
| |
| QDateTime::QDateTime(const QDateTime &other) |
| : d(other.d) |
| { |
| } |
| |
| /*! |
| Destroys the datetime. |
| */ |
| QDateTime::~QDateTime() |
| { |
| } |
| |
| /*! |
| Makes a copy of the \a other datetime and returns a reference to the |
| copy. |
| */ |
| |
| QDateTime &QDateTime::operator=(const QDateTime &other) |
| { |
| d = other.d; |
| return *this; |
| } |
| |
| /*! |
| Returns true if both the date and the time are null; otherwise |
| returns false. A null datetime is invalid. |
| |
| \sa QDate::isNull(), QTime::isNull(), isValid() |
| */ |
| |
| bool QDateTime::isNull() const |
| { |
| return d->date.isNull() && d->time.isNull(); |
| } |
| |
| /*! |
| Returns true if both the date and the time are valid; otherwise |
| returns false. |
| |
| \sa QDate::isValid(), QTime::isValid() |
| */ |
| |
| bool QDateTime::isValid() const |
| { |
| return d->date.isValid() && d->time.isValid(); |
| } |
| |
| /*! |
| Returns the date part of the datetime. |
| |
| \sa setDate(), time(), timeSpec() |
| */ |
| |
| QDate QDateTime::date() const |
| { |
| return d->date; |
| } |
| |
| /*! |
| Returns the time part of the datetime. |
| |
| \sa setTime(), date(), timeSpec() |
| */ |
| |
| QTime QDateTime::time() const |
| { |
| return d->time; |
| } |
| |
| /*! |
| Returns the time specification of the datetime. |
| |
| \sa setTimeSpec(), date(), time(), Qt::TimeSpec |
| */ |
| |
| Qt::TimeSpec QDateTime::timeSpec() const |
| { |
| switch(d->spec) |
| { |
| case QDateTimePrivate::UTC: |
| return Qt::UTC; |
| case QDateTimePrivate::OffsetFromUTC: |
| return Qt::OffsetFromUTC; |
| default: |
| return Qt::LocalTime; |
| } |
| } |
| |
| /*! |
| Sets the date part of this datetime to \a date. |
| If no time is set, it is set to midnight. |
| |
| \sa date(), setTime(), setTimeSpec() |
| */ |
| |
| void QDateTime::setDate(const QDate &date) |
| { |
| detach(); |
| d->date = date; |
| if (d->spec == QDateTimePrivate::LocalStandard |
| || d->spec == QDateTimePrivate::LocalDST) |
| d->spec = QDateTimePrivate::LocalUnknown; |
| if (date.isValid() && !d->time.isValid()) |
| d->time = QTime(0, 0, 0); |
| } |
| |
| /*! |
| Sets the time part of this datetime to \a time. |
| |
| \sa time(), setDate(), setTimeSpec() |
| */ |
| |
| void QDateTime::setTime(const QTime &time) |
| { |
| detach(); |
| if (d->spec == QDateTimePrivate::LocalStandard |
| || d->spec == QDateTimePrivate::LocalDST) |
| d->spec = QDateTimePrivate::LocalUnknown; |
| d->time = time; |
| } |
| |
| /*! |
| Sets the time specification used in this datetime to \a spec. |
| |
| \sa timeSpec(), setDate(), setTime(), Qt::TimeSpec |
| */ |
| |
| void QDateTime::setTimeSpec(Qt::TimeSpec spec) |
| { |
| detach(); |
| |
| switch(spec) |
| { |
| case Qt::UTC: |
| d->spec = QDateTimePrivate::UTC; |
| break; |
| case Qt::OffsetFromUTC: |
| d->spec = QDateTimePrivate::OffsetFromUTC; |
| break; |
| default: |
| d->spec = QDateTimePrivate::LocalUnknown; |
| break; |
| } |
| } |
| |
| qint64 toMSecsSinceEpoch_helper(qint64 jd, int msecs) |
| { |
| qint64 days = jd - JULIAN_DAY_FOR_EPOCH; |
| qint64 retval = (days * MSECS_PER_DAY) + msecs; |
| return retval; |
| } |
| |
| /*! |
| \since 4.7 |
| |
| Returns the datetime as the number of milliseconds that have passed |
| since 1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC). |
| |
| On systems that do not support time zones, this function will |
| behave as if local time were Qt::UTC. |
| |
| The behavior for this function is undefined if the datetime stored in |
| this object is not valid. However, for all valid dates, this function |
| returns a unique value. |
| |
| \sa toTime_t(), setMSecsSinceEpoch() |
| */ |
| qint64 QDateTime::toMSecsSinceEpoch() const |
| { |
| QDate utcDate; |
| QTime utcTime; |
| d->getUTC(utcDate, utcTime); |
| |
| return toMSecsSinceEpoch_helper(utcDate.jd, utcTime.ds()); |
| } |
| |
| /*! |
| Returns the datetime as the number of seconds that have passed |
| since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC). |
| |
| On systems that do not support time zones, this function will |
| behave as if local time were Qt::UTC. |
| |
| \note This function returns a 32-bit unsigned integer, so it does not |
| support dates before 1970, but it does support dates after |
| 2038-01-19T03:14:06, which may not be valid time_t values. Be careful |
| when passing those time_t values to system functions, which could |
| interpret them as negative dates. |
| |
| If the date is outside the range 1970-01-01T00:00:00 to |
| 2106-02-07T06:28:14, this function returns -1 cast to an unsigned integer |
| (i.e., 0xFFFFFFFF). |
| |
| To get an extended range, use toMSecsSinceEpoch(). |
| |
| \sa toMSecsSinceEpoch(), setTime_t() |
| */ |
| |
| uint QDateTime::toTime_t() const |
| { |
| qint64 retval = toMSecsSinceEpoch() / 1000; |
| if (quint64(retval) >= Q_UINT64_C(0xFFFFFFFF)) |
| return uint(-1); |
| return uint(retval); |
| } |
| |
| /*! |
| \since 4.7 |
| |
| Sets the date and time given the number of milliseconds,\a msecs, that have |
| passed since 1970-01-01T00:00:00.000, Coordinated Universal Time |
| (Qt::UTC). On systems that do not support time zones this function |
| will behave as if local time were Qt::UTC. |
| |
| Note that there are possible values for \a msecs that lie outside the |
| valid range of QDateTime, both negative and positive. The behavior of |
| this function is undefined for those values. |
| |
| \sa toMSecsSinceEpoch(), setTime_t() |
| */ |
| void QDateTime::setMSecsSinceEpoch(qint64 msecs) |
| { |
| detach(); |
| |
| QDateTimePrivate::Spec oldSpec = d->spec; |
| |
| int ddays = msecs / MSECS_PER_DAY; |
| msecs %= MSECS_PER_DAY; |
| if (msecs < 0) { |
| // negative |
| --ddays; |
| msecs += MSECS_PER_DAY; |
| } |
| |
| d->date = QDate(1970, 1, 1).addDays(ddays); |
| d->time = QTime().addMSecs(msecs); |
| d->spec = QDateTimePrivate::UTC; |
| |
| if (oldSpec != QDateTimePrivate::UTC) |
| d->spec = d->getLocal(d->date, d->time); |
| } |
| |
| /*! |
| \fn void QDateTime::setTime_t(uint seconds) |
| |
| Sets the date and time given the number of \a seconds that have |
| passed since 1970-01-01T00:00:00, Coordinated Universal Time |
| (Qt::UTC). On systems that do not support time zones this function |
| will behave as if local time were Qt::UTC. |
| |
| \sa toTime_t() |
| */ |
| |
| void QDateTime::setTime_t(uint secsSince1Jan1970UTC) |
| { |
| detach(); |
| |
| QDateTimePrivate::Spec oldSpec = d->spec; |
| |
| d->date = QDate(1970, 1, 1).addDays(secsSince1Jan1970UTC / SECS_PER_DAY); |
| d->time = QTime().addSecs(secsSince1Jan1970UTC % SECS_PER_DAY); |
| d->spec = QDateTimePrivate::UTC; |
| |
| if (oldSpec != QDateTimePrivate::UTC) |
| d->spec = d->getLocal(d->date, d->time); |
| } |
| |
| #ifndef QT_NO_DATESTRING |
| /*! |
| \fn QString QDateTime::toString(Qt::DateFormat format) const |
| |
| \overload |
| |
| Returns the datetime as a string in the \a format given. |
| |
| If the \a format is Qt::TextDate, the string is formatted in |
| the default way. QDate::shortDayName(), QDate::shortMonthName(), |
| and QTime::toString() are used to generate the string, so the |
| day and month names will be localized names. An example of this |
| formatting is "Wed May 20 03:40:13 1998". |
| |
| If the \a format is Qt::ISODate, the string format corresponds |
| to the ISO 8601 extended specification for representations of |
| dates and times, taking the form YYYY-MM-DDTHH:MM:SS. |
| |
| If the \a format is Qt::SystemLocaleShortDate or |
| Qt::SystemLocaleLongDate, the string format depends on the locale |
| settings of the system. Identical to calling |
| QLocale::system().toString(datetime, QLocale::ShortFormat) or |
| QLocale::system().toString(datetime, QLocale::LongFormat). |
| |
| If the \a format is Qt::DefaultLocaleShortDate or |
| Qt::DefaultLocaleLongDate, the string format depends on the |
| default application locale. This is the locale set with |
| QLocale::setDefault(), or the system locale if no default locale |
| has been set. Identical to calling QLocale().toString(datetime, |
| QLocale::ShortFormat) or QLocale().toString(datetime, |
| QLocale::LongFormat). |
| |
| If the datetime is invalid, an empty string will be returned. |
| |
| \warning The Qt::ISODate format is only valid for years in the |
| range 0 to 9999. This restriction may apply to locale-aware |
| formats as well, depending on the locale settings. |
| |
| \sa QDate::toString() QTime::toString() Qt::DateFormat |
| */ |
| |
| QString QDateTime::toString(Qt::DateFormat f) const |
| { |
| QString buf; |
| if (!isValid()) |
| return buf; |
| |
| if (f == Qt::ISODate) { |
| buf = d->date.toString(Qt::ISODate); |
| if (buf.isEmpty()) |
| return QString(); // failed to convert |
| buf += QLatin1Char('T'); |
| buf += d->time.toString(Qt::ISODate); |
| } |
| #ifndef QT_NO_TEXTDATE |
| else if (f == Qt::TextDate) { |
| #ifndef Q_WS_WIN |
| buf = d->date.shortDayName(d->date.dayOfWeek()); |
| buf += QLatin1Char(' '); |
| buf += d->date.shortMonthName(d->date.month()); |
| buf += QLatin1Char(' '); |
| buf += QString::number(d->date.day()); |
| #else |
| wchar_t out[255]; |
| GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255); |
| QString winstr = QString::fromWCharArray(out); |
| switch (winstr.toInt()) { |
| case 1: |
| buf = d->date.shortDayName(d->date.dayOfWeek()); |
| buf += QLatin1Char(' '); |
| buf += QString::number(d->date.day()); |
| buf += QLatin1String(". "); |
| buf += d->date.shortMonthName(d->date.month()); |
| break; |
| default: |
| buf = d->date.shortDayName(d->date.dayOfWeek()); |
| buf += QLatin1Char(' '); |
| buf += d->date.shortMonthName(d->date.month()); |
| buf += QLatin1Char(' '); |
| buf += QString::number(d->date.day()); |
| } |
| #endif |
| buf += QLatin1Char(' '); |
| buf += d->time.toString(); |
| buf += QLatin1Char(' '); |
| buf += QString::number(d->date.year()); |
| } |
| #endif |
| else { |
| buf = d->date.toString(f); |
| if (buf.isEmpty()) |
| return QString(); // failed to convert |
| buf += QLatin1Char(' '); |
| buf += d->time.toString(f); |
| } |
| |
| return buf; |
| } |
| |
| /*! |
| Returns the datetime as a string. The \a format parameter |
| determines the format of the result string. |
| |
| These expressions may be used for the date: |
| |
| \table |
| \header \i Expression \i Output |
| \row \i d \i the day as number without a leading zero (1 to 31) |
| \row \i dd \i the day as number with a leading zero (01 to 31) |
| \row \i ddd |
| \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). |
| Uses QDate::shortDayName(). |
| \row \i dddd |
| \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday'). |
| Uses QDate::longDayName(). |
| \row \i M \i the month as number without a leading zero (1-12) |
| \row \i MM \i the month as number with a leading zero (01-12) |
| \row \i MMM |
| \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). |
| Uses QDate::shortMonthName(). |
| \row \i MMMM |
| \i the long localized month name (e.g. 'January' to 'December'). |
| Uses QDate::longMonthName(). |
| \row \i yy \i the year as two digit number (00-99) |
| \row \i yyyy \i the year as four digit number |
| \endtable |
| |
| These expressions may be used for the time: |
| |
| \table |
| \header \i Expression \i Output |
| \row \i h |
| \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) |
| \row \i hh |
| \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) |
| \row \i m \i the minute without a leading zero (0 to 59) |
| \row \i mm \i the minute with a leading zero (00 to 59) |
| \row \i s \i the second without a leading zero (0 to 59) |
| \row \i ss \i the second with a leading zero (00 to 59) |
| \row \i z \i the milliseconds without leading zeroes (0 to 999) |
| \row \i zzz \i the milliseconds with leading zeroes (000 to 999) |
| \row \i AP |
| \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". |
| \row \i ap |
| \i use am/pm display. \e ap will be replaced by either "am" or "pm". |
| \endtable |
| |
| All other input characters will be ignored. Any sequence of characters that |
| are enclosed in singlequotes will be treated as text and not be used as an |
| expression. Two consecutive singlequotes ("''") are replaced by a singlequote |
| in the output. |
| |
| Example format strings (assumed that the QDateTime is 21 May 2001 |
| 14:13:09): |
| |
| \table |
| \header \i Format \i Result |
| \row \i dd.MM.yyyy \i 21.05.2001 |
| \row \i ddd MMMM d yy \i Tue May 21 01 |
| \row \i hh:mm:ss.zzz \i 14:13:09.042 |
| \row \i h:m:s ap \i 2:13:9 pm |
| \endtable |
| |
| If the datetime is invalid, an empty string will be returned. |
| |
| \sa QDate::toString() QTime::toString() |
| */ |
| QString QDateTime::toString(const QString& format) const |
| { |
| return fmtDateTime(format, &d->time, &d->date); |
| } |
| #endif //QT_NO_DATESTRING |
| |
| /*! |
| Returns a QDateTime object containing a datetime \a ndays days |
| later than the datetime of this object (or earlier if \a ndays is |
| negative). |
| |
| \sa daysTo(), addMonths(), addYears(), addSecs() |
| */ |
| |
| QDateTime QDateTime::addDays(int ndays) const |
| { |
| return QDateTime(d->date.addDays(ndays), d->time, timeSpec()); |
| } |
| |
| /*! |
| Returns a QDateTime object containing a datetime \a nmonths months |
| later than the datetime of this object (or earlier if \a nmonths |
| is negative). |
| |
| \sa daysTo(), addDays(), addYears(), addSecs() |
| */ |
| |
| QDateTime QDateTime::addMonths(int nmonths) const |
| { |
| return QDateTime(d->date.addMonths(nmonths), d->time, timeSpec()); |
| } |
| |
| /*! |
| Returns a QDateTime object containing a datetime \a nyears years |
| later than the datetime of this object (or earlier if \a nyears is |
| negative). |
| |
| \sa daysTo(), addDays(), addMonths(), addSecs() |
| */ |
| |
| QDateTime QDateTime::addYears(int nyears) const |
| { |
| return QDateTime(d->date.addYears(nyears), d->time, timeSpec()); |
| } |
| |
| QDateTime QDateTimePrivate::addMSecs(const QDateTime &dt, qint64 msecs) |
| { |
| QDate utcDate; |
| QTime utcTime; |
| dt.d->getUTC(utcDate, utcTime); |
| |
| addMSecs(utcDate, utcTime, msecs); |
| |
| return QDateTime(utcDate, utcTime, Qt::UTC).toTimeSpec(dt.timeSpec()); |
| } |
| |
| /*! |
| Adds \a msecs to utcDate and \a utcTime as appropriate. It is assumed that |
| utcDate and utcTime are adjusted to UTC. |
| |
| \since 4.5 |
| \internal |
| */ |
| void QDateTimePrivate::addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs) |
| { |
| uint dd = utcDate.jd; |
| int tt = utcTime.ds(); |
| int sign = 1; |
| if (msecs < 0) { |
| msecs = -msecs; |
| sign = -1; |
| } |
| if (msecs >= int(MSECS_PER_DAY)) { |
| dd += sign * (msecs / MSECS_PER_DAY); |
| msecs %= MSECS_PER_DAY; |
| } |
| |
| tt += sign * msecs; |
| if (tt < 0) { |
| tt = MSECS_PER_DAY - tt - 1; |
| dd -= tt / MSECS_PER_DAY; |
| tt = tt % MSECS_PER_DAY; |
| tt = MSECS_PER_DAY - tt - 1; |
| } else if (tt >= int(MSECS_PER_DAY)) { |
| dd += tt / MSECS_PER_DAY; |
| tt = tt % MSECS_PER_DAY; |
| } |
| |
| utcDate.jd = dd; |
| utcTime.mds = tt; |
| } |
| |
| /*! |
| Returns a QDateTime object containing a datetime \a s seconds |
| later than the datetime of this object (or earlier if \a s is |
| negative). |
| |
| \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears() |
| */ |
| |
| QDateTime QDateTime::addSecs(int s) const |
| { |
| return d->addMSecs(*this, qint64(s) * 1000); |
| } |
| |
| /*! |
| Returns a QDateTime object containing a datetime \a msecs miliseconds |
| later than the datetime of this object (or earlier if \a msecs is |
| negative). |
| |
| \sa addSecs(), msecsTo(), addDays(), addMonths(), addYears() |
| */ |
| QDateTime QDateTime::addMSecs(qint64 msecs) const |
| { |
| return d->addMSecs(*this, msecs); |
| } |
| |
| /*! |
| Returns the number of days from this datetime to the \a other |
| datetime. If the \a other datetime is earlier than this datetime, |
| the value returned is negative. |
| |
| \sa addDays(), secsTo(), msecsTo() |
| */ |
| |
| int QDateTime::daysTo(const QDateTime &other) const |
| { |
| return d->date.daysTo(other.d->date); |
| } |
| |
| /*! |
| Returns the number of seconds from this datetime to the \a other |
| datetime. If the \a other datetime is earlier than this datetime, |
| the value returned is negative. |
| |
| Before performing the comparison, the two datetimes are converted |
| to Qt::UTC to ensure that the result is correct if one of the two |
| datetimes has daylight saving time (DST) and the other doesn't. |
| |
| Example: |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 11 |
| |
| \sa addSecs(), daysTo(), QTime::secsTo() |
| */ |
| |
| int QDateTime::secsTo(const QDateTime &other) const |
| { |
| QDate date1, date2; |
| QTime time1, time2; |
| |
| d->getUTC(date1, time1); |
| other.d->getUTC(date2, time2); |
| |
| return (date1.daysTo(date2) * SECS_PER_DAY) + time1.secsTo(time2); |
| } |
| |
| /*! |
| Returns the number of milliseconds from this datetime to the \a other |
| datetime. If the \a other datetime is earlier than this datetime, |
| the value returned is negative. |
| |
| Before performing the comparison, the two datetimes are converted |
| to Qt::UTC to ensure that the result is correct if one of the two |
| datetimes has daylight saving time (DST) and the other doesn't. |
| |
| \sa addMSecs(), daysTo(), QTime::msecsTo() |
| */ |
| |
| qint64 QDateTime::msecsTo(const QDateTime &other) const |
| { |
| QDate selfDate; |
| QDate otherDate; |
| QTime selfTime; |
| QTime otherTime; |
| |
| d->getUTC(selfDate, selfTime); |
| other.d->getUTC(otherDate, otherTime); |
| |
| return (static_cast<qint64>(selfDate.daysTo(otherDate)) * static_cast<qint64>(MSECS_PER_DAY)) |
| + static_cast<qint64>(selfTime.msecsTo(otherTime)); |
| } |
| |
| |
| /*! |
| \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec specification) const |
| |
| Returns a copy of this datetime configured to use the given time |
| \a specification. |
| |
| \sa timeSpec(), toUTC(), toLocalTime() |
| */ |
| |
| QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const |
| { |
| if ((d->spec == QDateTimePrivate::UTC) == (spec == Qt::UTC)) |
| return *this; |
| |
| QDateTime ret; |
| if (spec == Qt::UTC) { |
| d->getUTC(ret.d->date, ret.d->time); |
| ret.d->spec = QDateTimePrivate::UTC; |
| } else { |
| ret.d->spec = d->getLocal(ret.d->date, ret.d->time); |
| } |
| return ret; |
| } |
| |
| /*! |
| Returns true if this datetime is equal to the \a other datetime; |
| otherwise returns false. |
| |
| \sa operator!=() |
| */ |
| |
| bool QDateTime::operator==(const QDateTime &other) const |
| { |
| if (d->spec == other.d->spec && d->utcOffset == other.d->utcOffset) |
| return d->time == other.d->time && d->date == other.d->date; |
| else { |
| QDate date1, date2; |
| QTime time1, time2; |
| |
| d->getUTC(date1, time1); |
| other.d->getUTC(date2, time2); |
| return time1 == time2 && date1 == date2; |
| } |
| } |
| |
| /*! |
| \fn bool QDateTime::operator!=(const QDateTime &other) const |
| |
| Returns true if this datetime is different from the \a other |
| datetime; otherwise returns false. |
| |
| Two datetimes are different if either the date, the time, or the |
| time zone components are different. |
| |
| \sa operator==() |
| */ |
| |
| /*! |
| Returns true if this datetime is earlier than the \a other |
| datetime; otherwise returns false. |
| */ |
| |
| bool QDateTime::operator<(const QDateTime &other) const |
| { |
| if (d->spec == other.d->spec && d->spec != QDateTimePrivate::OffsetFromUTC) { |
| if (d->date != other.d->date) |
| return d->date < other.d->date; |
| return d->time < other.d->time; |
| } else { |
| QDate date1, date2; |
| QTime time1, time2; |
| d->getUTC(date1, time1); |
| other.d->getUTC(date2, time2); |
| if (date1 != date2) |
| return date1 < date2; |
| return time1 < time2; |
| } |
| } |
| |
| /*! |
| \fn bool QDateTime::operator<=(const QDateTime &other) const |
| |
| Returns true if this datetime is earlier than or equal to the |
| \a other datetime; otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QDateTime::operator>(const QDateTime &other) const |
| |
| Returns true if this datetime is later than the \a other datetime; |
| otherwise returns false. |
| */ |
| |
| /*! |
| \fn bool QDateTime::operator>=(const QDateTime &other) const |
| |
| Returns true if this datetime is later than or equal to the |
| \a other datetime; otherwise returns false. |
| */ |
| |
| /*! |
| \fn QDateTime QDateTime::currentDateTime() |
| Returns the current datetime, as reported by the system clock, in |
| the local time zone. |
| |
| \sa currentDateTimeUtc(), QDate::currentDate(), QTime::currentTime(), toTimeSpec() |
| */ |
| |
| /*! |
| \fn QDateTime QDateTime::currentDateTimeUtc() |
| \since 4.7 |
| Returns the current datetime, as reported by the system clock, in |
| UTC. |
| |
| \sa currentDateTime(), QDate::currentDate(), QTime::currentTime(), toTimeSpec() |
| */ |
| |
| /*! |
| \fn qint64 QDateTime::currentMSecsSinceEpoch() |
| \since 4.7 |
| |
| Returns the number of milliseconds since 1970-01-01T00:00:00 Universal |
| Coordinated Time. This number is like the POSIX time_t variable, but |
| expressed in milliseconds instead. |
| |
| \sa currentDateTime(), currentDateTimeUtc(), toTime_t(), toTimeSpec() |
| */ |
| |
| static inline uint msecsFromDecomposed(int hour, int minute, int sec, int msec = 0) |
| { |
| return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + 1000 * sec + msec; |
| } |
| |
| #if defined(Q_OS_WIN) |
| QDate QDate::currentDate() |
| { |
| QDate d; |
| SYSTEMTIME st; |
| memset(&st, 0, sizeof(SYSTEMTIME)); |
| GetLocalTime(&st); |
| d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay); |
| return d; |
| } |
| |
| QTime QTime::currentTime() |
| { |
| QTime ct; |
| SYSTEMTIME st; |
| memset(&st, 0, sizeof(SYSTEMTIME)); |
| GetLocalTime(&st); |
| ct.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); |
| #if defined(Q_OS_WINCE) |
| ct.startTick = GetTickCount() % MSECS_PER_DAY; |
| #endif |
| return ct; |
| } |
| |
| QDateTime QDateTime::currentDateTime() |
| { |
| QDate d; |
| QTime t; |
| SYSTEMTIME st; |
| memset(&st, 0, sizeof(SYSTEMTIME)); |
| GetLocalTime(&st); |
| d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay); |
| t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); |
| return QDateTime(d, t); |
| } |
| |
| QDateTime QDateTime::currentDateTimeUtc() |
| { |
| QDate d; |
| QTime t; |
| SYSTEMTIME st; |
| memset(&st, 0, sizeof(SYSTEMTIME)); |
| GetSystemTime(&st); |
| d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay); |
| t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); |
| return QDateTime(d, t, Qt::UTC); |
| } |
| |
| qint64 QDateTime::currentMSecsSinceEpoch() |
| { |
| QDate d; |
| QTime t; |
| SYSTEMTIME st; |
| memset(&st, 0, sizeof(SYSTEMTIME)); |
| GetSystemTime(&st); |
| |
| return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) + |
| qint64(julianDayFromGregorianDate(st.wYear, st.wMonth, st.wDay) |
| - julianDayFromGregorianDate(1970, 1, 1)) * Q_INT64_C(86400000); |
| } |
| |
| #elif defined(Q_OS_SYMBIAN) |
| QDate QDate::currentDate() |
| { |
| QDate d; |
| TTime localTime; |
| localTime.HomeTime(); |
| TDateTime localDateTime = localTime.DateTime(); |
| // months and days are zero indexed |
| d.jd = julianDayFromDate(localDateTime.Year(), localDateTime.Month() + 1, localDateTime.Day() + 1 ); |
| return d; |
| } |
| |
| QTime QTime::currentTime() |
| { |
| QTime ct; |
| TTime localTime; |
| localTime.HomeTime(); |
| TDateTime localDateTime = localTime.DateTime(); |
| ct.mds = msecsFromDecomposed(localDateTime.Hour(), localDateTime.Minute(), |
| localDateTime.Second(), localDateTime.MicroSecond() / 1000); |
| return ct; |
| } |
| |
| QDateTime QDateTime::currentDateTime() |
| { |
| QDate d; |
| QTime ct; |
| TTime localTime; |
| localTime.HomeTime(); |
| TDateTime localDateTime = localTime.DateTime(); |
| // months and days are zero indexed |
| d.jd = julianDayFromDate(localDateTime.Year(), localDateTime.Month() + 1, localDateTime.Day() + 1); |
| ct.mds = msecsFromDecomposed(localDateTime.Hour(), localDateTime.Minute(), |
| localDateTime.Second(), localDateTime.MicroSecond() / 1000); |
| return QDateTime(d, ct); |
| } |
| |
| QDateTime QDateTime::currentDateTimeUtc() |
| { |
| QDate d; |
| QTime ct; |
| TTime gmTime; |
| gmTime.UniversalTime(); |
| TDateTime gmtDateTime = gmTime.DateTime(); |
| // months and days are zero indexed |
| d.jd = julianDayFromDate(gmtDateTime.Year(), gmtDateTime.Month() + 1, gmtDateTime.Day() + 1); |
| ct.mds = msecsFromDecomposed(gmtDateTime.Hour(), gmtDateTime.Minute(), |
| gmtDateTime.Second(), gmtDateTime.MicroSecond() / 1000); |
| return QDateTime(d, ct, Qt::UTC); |
| } |
| |
| qint64 QDateTime::currentMSecsSinceEpoch() |
| { |
| QDate d; |
| QTime ct; |
| TTime gmTime; |
| gmTime.UniversalTime(); |
| TDateTime gmtDateTime = gmTime.DateTime(); |
| |
| // according to the documentation, the value is: |
| // "a date and time as a number of microseconds since midnight, January 1st, 0 AD nominal Gregorian" |
| qint64 value = gmTime.Int64(); |
| |
| // whereas 1970-01-01T00:00:00 is (in the same representation): |
| // ((1970 * 365) + (1970 / 4) - (1970 / 100) + (1970 / 400) - 13) * 86400 * 1000000 |
| static const qint64 unixEpoch = Q_INT64_C(0xdcddb30f2f8000); |
| |
| return (value - unixEpoch) / 1000; |
| } |
| |
| #elif defined(Q_OS_UNIX) |
| QDate QDate::currentDate() |
| { |
| QDate d; |
| // posix compliant system |
| time_t ltime; |
| time(<ime); |
| struct tm *t = 0; |
| |
| #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) |
| // use the reentrant version of localtime() where available |
| tzset(); |
| struct tm res; |
| t = localtime_r(<ime, &res); |
| #else |
| t = localtime(<ime); |
| #endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS |
| |
| d.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday); |
| return d; |
| } |
| |
| QTime QTime::currentTime() |
| { |
| QTime ct; |
| // posix compliant system |
| struct timeval tv; |
| gettimeofday(&tv, 0); |
| time_t ltime = tv.tv_sec; |
| struct tm *t = 0; |
| |
| #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) |
| // use the reentrant version of localtime() where available |
| tzset(); |
| struct tm res; |
| t = localtime_r(<ime, &res); |
| #else |
| t = localtime(<ime); |
| #endif |
| Q_CHECK_PTR(t); |
| |
| ct.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000); |
| return ct; |
| } |
| |
| QDateTime QDateTime::currentDateTime() |
| { |
| // posix compliant system |
| // we have milliseconds |
| struct timeval tv; |
| gettimeofday(&tv, 0); |
| time_t ltime = tv.tv_sec; |
| struct tm *t = 0; |
| |
| #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) |
| // use the reentrant version of localtime() where available |
| tzset(); |
| struct tm res; |
| t = localtime_r(<ime, &res); |
| #else |
| t = localtime(<ime); |
| #endif |
| |
| QDateTime dt; |
| dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000); |
| |
| dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday); |
| dt.d->spec = t->tm_isdst > 0 ? QDateTimePrivate::LocalDST : |
| t->tm_isdst == 0 ? QDateTimePrivate::LocalStandard : |
| QDateTimePrivate::LocalUnknown; |
| return dt; |
| } |
| |
| QDateTime QDateTime::currentDateTimeUtc() |
| { |
| // posix compliant system |
| // we have milliseconds |
| struct timeval tv; |
| gettimeofday(&tv, 0); |
| time_t ltime = tv.tv_sec; |
| struct tm *t = 0; |
| |
| #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) |
| // use the reentrant version of localtime() where available |
| struct tm res; |
| t = gmtime_r(<ime, &res); |
| #else |
| t = gmtime(<ime); |
| #endif |
| |
| QDateTime dt; |
| dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000); |
| |
| dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday); |
| dt.d->spec = QDateTimePrivate::UTC; |
| return dt; |
| } |
| |
| qint64 QDateTime::currentMSecsSinceEpoch() |
| { |
| // posix compliant system |
| // we have milliseconds |
| struct timeval tv; |
| gettimeofday(&tv, 0); |
| return qint64(tv.tv_sec) * Q_INT64_C(1000) + tv.tv_usec / 1000; |
| } |
| |
| #else |
| #error "What system is this?" |
| #endif |
| |
| /*! |
| \since 4.2 |
| |
| Returns a datetime whose date and time are the number of \a seconds |
| that have passed since 1970-01-01T00:00:00, Coordinated Universal |
| Time (Qt::UTC). On systems that do not support time zones, the time |
| will be set as if local time were Qt::UTC. |
| |
| \sa toTime_t(), setTime_t() |
| */ |
| QDateTime QDateTime::fromTime_t(uint seconds) |
| { |
| QDateTime d; |
| d.setTime_t(seconds); |
| return d; |
| } |
| |
| /*! |
| \since 4.7 |
| |
| Returns a datetime whose date and time are the number of milliseconds, \a msecs, |
| that have passed since 1970-01-01T00:00:00.000, Coordinated Universal |
| Time (Qt::UTC). On systems that do not support time zones, the time |
| will be set as if local time were Qt::UTC. |
| |
| Note that there are possible values for \a msecs that lie outside the valid |
| range of QDateTime, both negative and positive. The behavior of this |
| function is undefined for those values. |
| |
| \sa toTime_t(), setTime_t() |
| */ |
| QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs) |
| { |
| QDateTime d; |
| d.setMSecsSinceEpoch(msecs); |
| return d; |
| } |
| |
| /*! |
| \since 4.4 |
| \internal |
| |
| Sets the offset from UTC to \a seconds, and also sets timeSpec() to |
| Qt::OffsetFromUTC. |
| |
| The maximum and minimum offset is 14 positive or negative hours. If |
| \a seconds is larger or smaller than that, the result is undefined. |
| |
| 0 as offset is identical to UTC. Therefore, if \a seconds is 0, the |
| timeSpec() will be set to Qt::UTC. Hence the UTC offset always |
| relates to UTC, and can never relate to local time. |
| |
| \sa isValid(), utcOffset() |
| */ |
| void QDateTime::setUtcOffset(int seconds) |
| { |
| detach(); |
| |
| /* The motivation to also setting d->spec is to ensure that the QDateTime |
| * instance stay in well-defined states all the time, instead of that |
| * we instruct the user to ensure it. */ |
| if(seconds == 0) |
| d->spec = QDateTimePrivate::UTC; |
| else |
| d->spec = QDateTimePrivate::OffsetFromUTC; |
| |
| /* Even if seconds is 0 we assign it to utcOffset. */ |
| d->utcOffset = seconds; |
| } |
| |
| /*! |
| \since 4.4 |
| \internal |
| |
| Returns the UTC offset in seconds. If the timeSpec() isn't |
| Qt::OffsetFromUTC, 0 is returned. However, since 0 is a valid UTC |
| offset the return value of this function cannot be used to determine |
| whether a utcOffset() is used or is valid, timeSpec() must be |
| checked. |
| |
| Likewise, if this QDateTime() is invalid or if timeSpec() isn't |
| Qt::OffsetFromUTC, 0 is returned. |
| |
| The UTC offset only applies if the timeSpec() is Qt::OffsetFromUTC. |
| |
| \sa isValid(), setUtcOffset() |
| */ |
| int QDateTime::utcOffset() const |
| { |
| if(isValid() && d->spec == QDateTimePrivate::OffsetFromUTC) |
| return d->utcOffset; |
| else |
| return 0; |
| } |
| |
| #ifndef QT_NO_DATESTRING |
| |
| static int fromShortMonthName(const QString &monthName) |
| { |
| // Assume that English monthnames are the default |
| for (int i = 0; i < 12; ++i) { |
| if (monthName == QLatin1String(qt_shortMonthNames[i])) |
| return i + 1; |
| } |
| // If English names can't be found, search the localized ones |
| for (int i = 1; i <= 12; ++i) { |
| if (monthName == QDate::shortMonthName(i)) |
| return i; |
| } |
| return -1; |
| } |
| |
| /*! |
| \fn QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format) |
| |
| Returns the QDateTime represented by the \a string, using the |
| \a format given, or an invalid datetime if this is not possible. |
| |
| Note for Qt::TextDate: It is recommended that you use the |
| English short month names (e.g. "Jan"). Although localized month |
| names can also be used, they depend on the user's locale settings. |
| */ |
| QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f) |
| { |
| if (s.isEmpty()) { |
| return QDateTime(); |
| } |
| |
| switch (f) { |
| case Qt::ISODate: { |
| QString tmp = s; |
| Qt::TimeSpec ts = Qt::LocalTime; |
| const QDate date = QDate::fromString(tmp.left(10), Qt::ISODate); |
| if (tmp.size() == 10) |
| return QDateTime(date); |
| |
| tmp = tmp.mid(11); |
| |
| // Recognize UTC specifications |
| if (tmp.endsWith(QLatin1Char('Z'))) { |
| ts = Qt::UTC; |
| tmp.chop(1); |
| } |
| |
| // Recognize timezone specifications |
| QRegExp rx(QLatin1String("[+-]")); |
| if (tmp.contains(rx)) { |
| int idx = tmp.indexOf(rx); |
| QString tmp2 = tmp.mid(idx); |
| tmp = tmp.left(idx); |
| bool ok = true; |
| int ntzhour = 1; |
| int ntzminute = 3; |
| if ( tmp2.indexOf(QLatin1Char(':')) == 3 ) |
| ntzminute = 4; |
| const int tzhour(tmp2.mid(ntzhour, 2).toInt(&ok)); |
| const int tzminute(tmp2.mid(ntzminute, 2).toInt(&ok)); |
| QTime tzt(tzhour, tzminute); |
| int utcOffset = (tzt.hour() * 60 + tzt.minute()) * 60; |
| if ( utcOffset != 0 ) { |
| ts = Qt::OffsetFromUTC; |
| QDateTime dt(date, QTime::fromString(tmp, Qt::ISODate), ts); |
| dt.setUtcOffset( utcOffset * (tmp2.startsWith(QLatin1Char('-')) ? -1 : 1) ); |
| return dt; |
| } |
| } |
| return QDateTime(date, QTime::fromString(tmp, Qt::ISODate), ts); |
| } |
| case Qt::SystemLocaleDate: |
| case Qt::SystemLocaleShortDate: |
| case Qt::SystemLocaleLongDate: |
| return fromString(s, QLocale::system().dateTimeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat |
| : QLocale::ShortFormat)); |
| case Qt::LocaleDate: |
| case Qt::DefaultLocaleShortDate: |
| case Qt::DefaultLocaleLongDate: |
| return fromString(s, QLocale().dateTimeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat |
| : QLocale::ShortFormat)); |
| #if !defined(QT_NO_TEXTDATE) |
| case Qt::TextDate: { |
| QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts); |
| |
| if ((parts.count() < 5) || (parts.count() > 6)) { |
| return QDateTime(); |
| } |
| |
| // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974" |
| int month = -1, day = -1; |
| bool ok; |
| |
| month = fromShortMonthName(parts.at(1)); |
| if (month != -1) { |
| day = parts.at(2).toInt(&ok); |
| if (!ok) |
| day = -1; |
| } |
| |
| if (month == -1 || day == -1) { |
| // first variant failed, lets try the other |
| month = fromShortMonthName(parts.at(2)); |
| if (month != -1) { |
| QString dayStr = parts.at(1); |
| if (dayStr.endsWith(QLatin1Char('.'))) { |
| dayStr.chop(1); |
| day = dayStr.toInt(&ok); |
| if (!ok) |
| day = -1; |
| } else { |
| day = -1; |
| } |
| } |
| } |
| |
| if (month == -1 || day == -1) { |
| // both variants failed, give up |
| return QDateTime(); |
| } |
| |
| int year; |
| QStringList timeParts = parts.at(3).split(QLatin1Char(':')); |
| if ((timeParts.count() == 3) || (timeParts.count() == 2)) { |
| year = parts.at(4).toInt(&ok); |
| if (!ok) |
| return QDateTime(); |
| } else { |
| timeParts = parts.at(4).split(QLatin1Char(':')); |
| if ((timeParts.count() != 3) && (timeParts.count() != 2)) |
| return QDateTime(); |
| year = parts.at(3).toInt(&ok); |
| if (!ok) |
| return QDateTime(); |
| } |
| |
| int hour = timeParts.at(0).toInt(&ok); |
| if (!ok) { |
| return QDateTime(); |
| } |
| |
| int minute = timeParts.at(1).toInt(&ok); |
| if (!ok) { |
| return QDateTime(); |
| } |
| |
| int second = (timeParts.count() > 2) ? timeParts.at(2).toInt(&ok) : 0; |
| if (!ok) { |
| return QDateTime(); |
| } |
| |
| QDate date(year, month, day); |
| QTime time(hour, minute, second); |
| |
| if (parts.count() == 5) |
| return QDateTime(date, time, Qt::LocalTime); |
| |
| QString tz = parts.at(5); |
| if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive)) |
| return QDateTime(); |
| int tzoffset = 0; |
| if (tz.length() > 3) { |
| QChar sign = tz.at(3); |
| if ((sign != QLatin1Char('+')) |
| && (sign != QLatin1Char('-'))) { |
| return QDateTime(); |
| } |
| int tzhour = tz.mid(4, 2).toInt(&ok); |
| if (!ok) |
| return QDateTime(); |
| int tzminute = tz.mid(6).toInt(&ok); |
| if (!ok) |
| return QDateTime(); |
| tzoffset = (tzhour*60 + tzminute) * 60; |
| if (sign == QLatin1Char('-')) |
| tzoffset = -tzoffset; |
| } |
| return QDateTime(date, time, Qt::UTC).addSecs(-tzoffset).toLocalTime(); |
| } |
| #endif //QT_NO_TEXTDATE |
| } |
| |
| return QDateTime(); |
| } |
| |
| /*! |
| \fn QDateTime::fromString(const QString &string, const QString &format) |
| |
| Returns the QDateTime represented by the \a string, using the \a |
| format given, or an invalid datetime if the string cannot be parsed. |
| |
| These expressions may be used for the date part of the format string: |
| |
| \table |
| \header \i Expression \i Output |
| \row \i d \i the day as number without a leading zero (1 to 31) |
| \row \i dd \i the day as number with a leading zero (01 to 31) |
| \row \i ddd |
| \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). |
| Uses QDate::shortDayName(). |
| \row \i dddd |
| \i the long localized day name (e.g. 'Monday' to 'Sunday'). |
| Uses QDate::longDayName(). |
| \row \i M \i the month as number without a leading zero (1-12) |
| \row \i MM \i the month as number with a leading zero (01-12) |
| \row \i MMM |
| \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). |
| Uses QDate::shortMonthName(). |
| \row \i MMMM |
| \i the long localized month name (e.g. 'January' to 'December'). |
| Uses QDate::longMonthName(). |
| \row \i yy \i the year as two digit number (00-99) |
| \row \i yyyy \i the year as four digit number |
| \endtable |
| |
| \note Unlike the other version of this function, day and month names must |
| be given in the user's local language. It is only possible to use the English |
| names if the user's language is English. |
| |
| These expressions may be used for the time part of the format string: |
| |
| \table |
| \header \i Expression \i Output |
| \row \i h |
| \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) |
| \row \i hh |
| \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) |
| \row \i H |
| \i the hour without a leading zero (0 to 23, even with AM/PM display) |
| \row \i HH |
| \i the hour with a leading zero (00 to 23, even with AM/PM display) |
| \row \i m \i the minute without a leading zero (0 to 59) |
| \row \i mm \i the minute with a leading zero (00 to 59) |
| \row \i s \i the second without a leading zero (0 to 59) |
| \row \i ss \i the second with a leading zero (00 to 59) |
| \row \i z \i the milliseconds without leading zeroes (0 to 999) |
| \row \i zzz \i the milliseconds with leading zeroes (000 to 999) |
| \row \i AP or A |
| \i interpret as an AM/PM time. \e AP must be either "AM" or "PM". |
| \row \i ap or a |
| \i Interpret as an AM/PM time. \e ap must be either "am" or "pm". |
| \endtable |
| |
| All other input characters will be treated as text. Any sequence |
| of characters that are enclosed in singlequotes will also be |
| treated as text and not be used as an expression. |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 12 |
| |
| If the format is not satisfied an invalid QDateTime is returned. |
| The expressions that don't have leading zeroes (d, M, h, m, s, z) will be |
| greedy. This means that they will use two digits even if this will |
| put them outside the range and/or leave too few digits for other |
| sections. |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 13 |
| |
| This could have meant 1 January 00:30.00 but the M will grab |
| two digits. |
| |
| For any field that is not represented in the format the following |
| defaults are used: |
| |
| \table |
| \header \i Field \i Default value |
| \row \i Year \i 1900 |
| \row \i Month \i 1 (January) |
| \row \i Day \i 1 |
| \row \i Hour \i 0 |
| \row \i Minute \i 0 |
| \row \i Second \i 0 |
| \endtable |
| |
| For example: |
| |
| \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 14 |
| |
| \sa QDate::fromString() QTime::fromString() QDate::toString() |
| QDateTime::toString() QTime::toString() |
| */ |
| |
| QDateTime QDateTime::fromString(const QString &string, const QString &format) |
| { |
| #ifndef QT_BOOTSTRAPPED |
| QTime time; |
| QDate date; |
| |
| QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString); |
| if (dt.parseFormat(format) && dt.fromString(string, &date, &time)) |
| return QDateTime(date, time); |
| #else |
| Q_UNUSED(string); |
| Q_UNUSED(format); |
| #endif |
| return QDateTime(QDate(), QTime(-1, -1, -1)); |
| } |
| |
| #endif // QT_NO_DATESTRING |
| /*! |
| \fn QDateTime QDateTime::toLocalTime() const |
| |
| Returns a datetime containing the date and time information in |
| this datetime, but specified using the Qt::LocalTime definition. |
| |
| \sa toTimeSpec() |
| */ |
| |
| /*! |
| \fn QDateTime QDateTime::toUTC() const |
| |
| Returns a datetime containing the date and time information in |
| this datetime, but specified using the Qt::UTC definition. |
| |
| \sa toTimeSpec() |
| */ |
| |
| /*! \internal |
| */ |
| void QDateTime::detach() |
| { |
| d.detach(); |
| } |
| |
| /***************************************************************************** |
| Date/time stream functions |
| *****************************************************************************/ |
| |
| #ifndef QT_NO_DATASTREAM |
| /*! |
| \relates QDate |
| |
| Writes the \a date to stream \a out. |
| |
| \sa {Serializing Qt Data Types} |
| */ |
| |
| QDataStream &operator<<(QDataStream &out, const QDate &date) |
| { |
| return out << (quint32)(date.jd); |
| } |
| |
| /*! |
| \relates QDate |
| |
| Reads a date from stream \a in into the \a date. |
| |
| \sa {Serializing Qt Data Types} |
| */ |
| |
| QDataStream &operator>>(QDataStream &in, QDate &date) |
| { |
| quint32 jd; |
| in >> jd; |
| date.jd = jd; |
| return in; |
| } |
| |
| /*! |
| \relates QTime |
| |
| Writes \a time to stream \a out. |
| |
| \sa {Serializing Qt Data Types} |
| */ |
| |
| QDataStream &operator<<(QDataStream &out, const QTime &time) |
| { |
| return out << quint32(time.mds); |
| } |
| |
| /*! |
| \relates QTime |
| |
| Reads a time from stream \a in into the given \a time. |
| |
| \sa {Serializing Qt Data Types} |
| */ |
| |
| QDataStream &operator>>(QDataStream &in, QTime &time) |
| { |
| quint32 ds; |
| in >> ds; |
| time.mds = int(ds); |
| return in; |
| } |
| |
| /*! |
| \relates QDateTime |
| |
| Writes \a dateTime to the \a out stream. |
| |
| \sa {Serializing Qt Data Types} |
| */ |
| QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime) |
| { |
| out << dateTime.d->date << dateTime.d->time; |
| if (out.version() >= 7) |
| out << (qint8)dateTime.d->spec; |
| return out; |
| } |
| |
| /*! |
| \relates QDateTime |
| |
| Reads a datetime from the stream \a in into \a dateTime. |
| |
| \sa {Serializing Qt Data Types} |
| */ |
| |
| QDataStream &operator>>(QDataStream &in, QDateTime &dateTime) |
| { |
| dateTime.detach(); |
| |
| qint8 ts = (qint8)QDateTimePrivate::LocalUnknown; |
| in >> dateTime.d->date >> dateTime.d->time; |
| if (in.version() >= 7) |
| in >> ts; |
| dateTime.d->spec = (QDateTimePrivate::Spec)ts; |
| return in; |
| } |
| #endif // QT_NO_DATASTREAM |
| |
| |
| /*! |
| \fn QString QDate::monthName(int month) |
| |
| Use shortMonthName() instead. |
| */ |
| |
| /*! |
| \fn QString QDate::dayName(int weekday) |
| |
| Use shortDayName() instead. |
| */ |
| |
| /*! |
| \fn bool QDate::leapYear(int year) |
| |
| Use isLeapYear() instead. |
| */ |
| |
| /*! |
| \fn QDate QDate::currentDate(Qt::TimeSpec spec) |
| |
| If \a spec is Qt::LocalTime, use the currentDate() overload that |
| takes no parameters instead; otherwise, use |
| QDateTime::currentDateTime(). |
| |
| \oldcode |
| QDate localDate = QDate::currentDate(Qt::LocalTime); |
| QDate utcDate = QDate::currentDate(Qt::UTC); |
| \newcode |
| QDate localDate = QDate::currentDate(); |
| QDate utcDate = QDateTime::currentDateTime().toUTC().date(); |
| \endcode |
| |
| \sa QDateTime::toUTC() |
| */ |
| |
| /*! |
| \fn QTime QTime::currentTime(Qt::TimeSpec specification) |
| |
| Returns the current time for the given \a specification. |
| |
| To replace uses of this function where the \a specification is Qt::LocalTime, |
| use the currentDate() overload that takes no parameters instead; otherwise, |
| use QDateTime::currentDateTime() and convert the result to a UTC measurement. |
| |
| \oldcode |
| QTime localTime = QTime::currentTime(Qt::LocalTime); |
| QTime utcTime = QTime::currentTime(Qt::UTC); |
| \newcode |
| QTime localTime = QTime::currentTime(); |
| QTime utcTime = QTimeTime::currentDateTime().toUTC().time(); |
| \endcode |
| |
| \sa QDateTime::toUTC() |
| */ |
| |
| /*! |
| \fn void QDateTime::setTime_t(uint secsSince1Jan1970UTC, Qt::TimeSpec spec) |
| |
| Use the single-argument overload of setTime_t() instead. |
| */ |
| |
| /*! |
| \fn QDateTime QDateTime::currentDateTime(Qt::TimeSpec spec) |
| |
| Use the currentDateTime() overload that takes no parameters |
| instead. |
| */ |
| |
| // checks if there is an unqoted 'AP' or 'ap' in the string |
| static bool hasUnquotedAP(const QString &f) |
| { |
| const QLatin1Char quote('\''); |
| bool inquote = false; |
| const int max = f.size(); |
| for (int i=0; i<max; ++i) { |
| if (f.at(i) == quote) { |
| inquote = !inquote; |
| } else if (!inquote && f.at(i).toUpper() == QLatin1Char('A')) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| #ifndef QT_NO_DATESTRING |
| /***************************************************************************** |
| Some static function used by QDate, QTime and QDateTime |
| *****************************************************************************/ |
| |
| // Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens |
| static QString getFmtString(const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = false) |
| { |
| if (f.isEmpty()) |
| return QString(); |
| |
| QString buf = f; |
| int removed = 0; |
| |
| if (dt) { |
| if (f.startsWith(QLatin1String("hh")) || f.startsWith(QLatin1String("HH"))) { |
| const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm; |
| if (hour12 && dt->hour() > 12) |
| buf = QString::number(dt->hour() - 12).rightJustified(2, QLatin1Char('0'), true); |
| else if (hour12 && dt->hour() == 0) |
| buf = QLatin1String("12"); |
| else |
| buf = QString::number(dt->hour()).rightJustified(2, QLatin1Char('0'), true); |
| removed = 2; |
| } else if (f.at(0) == QLatin1Char('h') || f.at(0) == QLatin1Char('H')) { |
| const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm; |
| if (hour12 && dt->hour() > 12) |
| buf = QString::number(dt->hour() - 12); |
| else if (hour12 && dt->hour() == 0) |
| buf = QLatin1String("12"); |
| else |
| buf = QString::number(dt->hour()); |
| removed = 1; |
| } else if (f.startsWith(QLatin1String("mm"))) { |
| buf = QString::number(dt->minute()).rightJustified(2, QLatin1Char('0'), true); |
| removed = 2; |
| } else if (f.at(0) == (QLatin1Char('m'))) { |
| buf = QString::number(dt->minute()); |
| removed = 1; |
| } else if (f.startsWith(QLatin1String("ss"))) { |
| buf = QString::number(dt->second()).rightJustified(2, QLatin1Char('0'), true); |
| removed = 2; |
| } else if (f.at(0) == QLatin1Char('s')) { |
| buf = QString::number(dt->second()); |
| } else if (f.startsWith(QLatin1String("zzz"))) { |
| buf = QString::number(dt->msec()).rightJustified(3, QLatin1Char('0'), true); |
| removed = 3; |
| } else if (f.at(0) == QLatin1Char('z')) { |
| buf = QString::number(dt->msec()); |
| removed = 1; |
| } else if (f.at(0).toUpper() == QLatin1Char('A')) { |
| const bool upper = f.at(0) == QLatin1Char('A'); |
| buf = dt->hour() < 12 ? QLatin1String("am") : QLatin1String("pm"); |
| if (upper) |
| buf = buf.toUpper(); |
| if (f.size() > 1 && f.at(1).toUpper() == QLatin1Char('P') && |
| f.at(0).isUpper() == f.at(1).isUpper()) { |
| removed = 2; |
| } else { |
| removed = 1; |
| } |
| } |
| } |
| |
| if (dd) { |
| if (f.startsWith(QLatin1String("dddd"))) { |
| buf = dd->longDayName(dd->dayOfWeek()); |
| removed = 4; |
| } else if (f.startsWith(QLatin1String("ddd"))) { |
| buf = dd->shortDayName(dd->dayOfWeek()); |
| removed = 3; |
| } else if (f.startsWith(QLatin1String("dd"))) { |
| buf = QString::number(dd->day()).rightJustified(2, QLatin1Char('0'), true); |
| removed = 2; |
| } else if (f.at(0) == QLatin1Char('d')) { |
| buf = QString::number(dd->day()); |
| removed = 1; |
| } else if (f.startsWith(QLatin1String("MMMM"))) { |
| buf = dd->longMonthName(dd->month()); |
| removed = 4; |
| } else if (f.startsWith(QLatin1String("MMM"))) { |
| buf = dd->shortMonthName(dd->month()); |
| removed = 3; |
| } else if (f.startsWith(QLatin1String("MM"))) { |
| buf = QString::number(dd->month()).rightJustified(2, QLatin1Char('0'), true); |
| removed = 2; |
| } else if (f.at(0) == QLatin1Char('M')) { |
| buf = QString::number(dd->month()); |
| removed = 1; |
| } else if (f.startsWith(QLatin1String("yyyy"))) { |
| const int year = dd->year(); |
| buf = QString::number(qAbs(year)).rightJustified(4, QLatin1Char('0')); |
| if(year > 0) |
| removed = 4; |
| else |
| { |
| buf.prepend(QLatin1Char('-')); |
| removed = 5; |
| } |
| |
| } else if (f.startsWith(QLatin1String("yy"))) { |
| buf = QString::number(dd->year()).right(2).rightJustified(2, QLatin1Char('0')); |
| removed = 2; |
| } |
| } |
| if (removed == 0 || removed >= f.size()) { |
| return buf; |
| } |
| |
| return buf + getFmtString(f.mid(removed), dt, dd, am_pm); |
| } |
| |
| // Parses the format string and uses getFmtString to get the values for the tokens. Ret |
| static QString fmtDateTime(const QString& f, const QTime* dt, const QDate* dd) |
| { |
| const QLatin1Char quote('\''); |
| if (f.isEmpty()) |
| return QString(); |
| if (dt && !dt->isValid()) |
| return QString(); |
| if (dd && !dd->isValid()) |
| return QString(); |
| |
| const bool ap = hasUnquotedAP(f); |
| |
| QString buf; |
| QString frm; |
| QChar status(QLatin1Char('0')); |
| |
| for (int i = 0; i < (int)f.length(); ++i) { |
| if (f.at(i) == quote) { |
| if (status == quote) { |
| if (i > 0 && f.at(i - 1) == quote) |
| buf += QLatin1Char('\''); |
| status = QLatin1Char('0'); |
| } else { |
| if (!frm.isEmpty()) { |
| buf += getFmtString(frm, dt, dd, ap); |
| frm.clear(); |
| } |
| status = quote; |
| } |
| } else if (status == quote) { |
| buf += f.at(i); |
| } else if (f.at(i) == status) { |
| if ((ap) && ((f.at(i) == QLatin1Char('P')) || (f.at(i) == QLatin1Char('p')))) |
| status = QLatin1Char('0'); |
| frm += f.at(i); |
| } else { |
| buf += getFmtString(frm, dt, dd, ap); |
| frm.clear(); |
| if ((f.at(i) == QLatin1Char('h')) || (f.at(i) == QLatin1Char('m')) |
| || (f.at(i) == QLatin1Char('H')) |
| || (f.at(i) == QLatin1Char('s')) || (f.at(i) == QLatin1Char('z'))) { |
| status = f.at(i); |
| frm += f.at(i); |
| } else if ((f.at(i) == QLatin1Char('d')) || (f.at(i) == QLatin1Char('M')) || (f.at(i) == QLatin1Char('y'))) { |
| status = f.at(i); |
| frm += f.at(i); |
| } else if ((ap) && (f.at(i) == QLatin1Char('A'))) { |
| status = QLatin1Char('P'); |
| frm += f.at(i); |
| } else if((ap) && (f.at(i) == QLatin1Char('a'))) { |
| status = QLatin1Char('p'); |
| frm += f.at(i); |
| } else { |
| buf += f.at(i); |
| status = QLatin1Char('0'); |
| } |
| } |
| } |
| |
| buf += getFmtString(frm, dt, dd, ap); |
| |
| return buf; |
| } |
| #endif // QT_NO_DATESTRING |
| |
| #ifdef Q_OS_WIN |
| static const int LowerYear = 1980; |
| #else |
| static const int LowerYear = 1970; |
| #endif |
| static const int UpperYear = 2037; |
| |
| static QDate adjustDate(QDate date) |
| { |
| QDate lowerLimit(LowerYear, 1, 2); |
| QDate upperLimit(UpperYear, 12, 30); |
| |
| if (date > lowerLimit && date < upperLimit) |
| return date; |
| |
| int month = date.month(); |
| int day = date.day(); |
| |
| // neither 1970 nor 2037 are leap years, so make sure date isn't Feb 29 |
| if (month == 2 && day == 29) |
| --day; |
| |
| if (date < lowerLimit) |
| date.setDate(LowerYear, month, day); |
| else |
| date.setDate(UpperYear, month, day); |
| |
| return date; |
| } |
| |
| static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time) |
| { |
| QDate fakeDate = adjustDate(date); |
| |
| // won't overflow because of fakeDate |
| time_t secsSince1Jan1970UTC = toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime().msecsTo(time)) / 1000; |
| tm *brokenDown = 0; |
| |
| #if defined(Q_OS_WINCE) |
| tm res; |
| FILETIME utcTime = time_tToFt(secsSince1Jan1970UTC); |
| FILETIME resultTime; |
| FileTimeToLocalFileTime(&utcTime , &resultTime); |
| SYSTEMTIME sysTime; |
| FileTimeToSystemTime(&resultTime , &sysTime); |
| |
| res.tm_sec = sysTime.wSecond; |
| res.tm_min = sysTime.wMinute; |
| res.tm_hour = sysTime.wHour; |
| res.tm_mday = sysTime.wDay; |
| res.tm_mon = sysTime.wMonth - 1; |
| res.tm_year = sysTime.wYear - 1900; |
| brokenDown = &res; |
| #elif defined(Q_OS_SYMBIAN) |
| // months and days are zero index based |
| _LIT(KUnixEpoch, "19700000:000000.000000"); |
| TTimeIntervalSeconds utcOffset = User::UTCOffset(); |
| TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC); |
| TTime epochTTime; |
| TInt err = epochTTime.Set(KUnixEpoch); |
| tm res; |
| if(err == KErrNone) { |
| TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC; |
| utcTTime = utcTTime + utcOffset; |
| TDateTime utcDateTime = utcTTime.DateTime(); |
| res.tm_sec = utcDateTime.Second(); |
| res.tm_min = utcDateTime.Minute(); |
| res.tm_hour = utcDateTime.Hour(); |
| res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct |
| res.tm_mon = utcDateTime.Month(); |
| res.tm_year = utcDateTime.Year() - 1900; |
| res.tm_isdst = 0; |
| brokenDown = &res; |
| } |
| #elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) |
| // use the reentrant version of localtime() where available |
| tzset(); |
| tm res; |
| brokenDown = localtime_r(&secsSince1Jan1970UTC, &res); |
| #elif defined(_MSC_VER) && _MSC_VER >= 1400 |
| tm res; |
| if (!_localtime64_s(&res, &secsSince1Jan1970UTC)) |
| brokenDown = &res; |
| #else |
| brokenDown = localtime(&secsSince1Jan1970UTC); |
| #endif |
| if (!brokenDown) { |
| date = QDate(1970, 1, 1); |
| time = QTime(); |
| return QDateTimePrivate::LocalUnknown; |
| } else { |
| int deltaDays = fakeDate.daysTo(date); |
| date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday); |
| time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec()); |
| date = date.addDays(deltaDays); |
| if (brokenDown->tm_isdst > 0) |
| return QDateTimePrivate::LocalDST; |
| else if (brokenDown->tm_isdst < 0) |
| return QDateTimePrivate::LocalUnknown; |
| else |
| return QDateTimePrivate::LocalStandard; |
| } |
| } |
| |
| static void localToUtc(QDate &date, QTime &time, int isdst) |
| { |
| if (!date.isValid()) |
| return; |
| |
| QDate fakeDate = adjustDate(date); |
| |
| tm localTM; |
| localTM.tm_sec = time.second(); |
| localTM.tm_min = time.minute(); |
| localTM.tm_hour = time.hour(); |
| localTM.tm_mday = fakeDate.day(); |
| localTM.tm_mon = fakeDate.month() - 1; |
| localTM.tm_year = fakeDate.year() - 1900; |
| localTM.tm_isdst = (int)isdst; |
| #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN) |
| time_t secsSince1Jan1970UTC = (toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime().msecsTo(time)) / 1000); |
| #else |
| #if defined(Q_OS_WIN) |
| _tzset(); |
| #endif |
| time_t secsSince1Jan1970UTC = mktime(&localTM); |
| #endif |
| tm *brokenDown = 0; |
| #if defined(Q_OS_WINCE) |
| tm res; |
| FILETIME localTime = time_tToFt(secsSince1Jan1970UTC); |
| SYSTEMTIME sysTime; |
| FileTimeToSystemTime(&localTime, &sysTime); |
| FILETIME resultTime; |
| LocalFileTimeToFileTime(&localTime , &resultTime); |
| FileTimeToSystemTime(&resultTime , &sysTime); |
| res.tm_sec = sysTime.wSecond; |
| res.tm_min = sysTime.wMinute; |
| res.tm_hour = sysTime.wHour; |
| res.tm_mday = sysTime.wDay; |
| res.tm_mon = sysTime.wMonth - 1; |
| res.tm_year = sysTime.wYear - 1900; |
| res.tm_isdst = (int)isdst; |
| brokenDown = &res; |
| #elif defined(Q_OS_SYMBIAN) |
| // months and days are zero index based |
| _LIT(KUnixEpoch, "19700000:000000.000000"); |
| TTimeIntervalSeconds utcOffset = TTimeIntervalSeconds(0 - User::UTCOffset().Int()); |
| TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC); |
| TTime epochTTime; |
| TInt err = epochTTime.Set(KUnixEpoch); |
| tm res; |
| if(err == KErrNone) { |
| TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC; |
| utcTTime = utcTTime + utcOffset; |
| TDateTime utcDateTime = utcTTime.DateTime(); |
| res.tm_sec = utcDateTime.Second(); |
| res.tm_min = utcDateTime.Minute(); |
| res.tm_hour = utcDateTime.Hour(); |
| res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct |
| res.tm_mon = utcDateTime.Month(); |
| res.tm_year = utcDateTime.Year() - 1900; |
| res.tm_isdst = (int)isdst; |
| brokenDown = &res; |
| } |
| #elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) |
| // use the reentrant version of gmtime() where available |
| tm res; |
| brokenDown = gmtime_r(&secsSince1Jan1970UTC, &res); |
| #elif defined(_MSC_VER) && _MSC_VER >= 1400 |
| tm res; |
| if (!_gmtime64_s(&res, &secsSince1Jan1970UTC)) |
| brokenDown = &res; |
| #else |
| brokenDown = gmtime(&secsSince1Jan1970UTC); |
| #endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS |
| if (!brokenDown) { |
| date = QDate(1970, 1, 1); |
| time = QTime(); |
| } else { |
| int deltaDays = fakeDate.daysTo(date); |
| date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday); |
| time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec()); |
| date = date.addDays(deltaDays); |
| } |
| } |
| |
| QDateTimePrivate::Spec QDateTimePrivate::getLocal(QDate &outDate, QTime &outTime) const |
| { |
| outDate = date; |
| outTime = time; |
| if (spec == QDateTimePrivate::UTC) |
| return utcToLocal(outDate, outTime); |
| return spec; |
| } |
| |
| void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const |
| { |
| outDate = date; |
| outTime = time; |
| const bool isOffset = spec == QDateTimePrivate::OffsetFromUTC; |
| |
| if (spec != QDateTimePrivate::UTC && !isOffset) |
| localToUtc(outDate, outTime, (int)spec); |
| |
| if (isOffset) |
| addMSecs(outDate, outTime, -(qint64(utcOffset) * 1000)); |
| } |
| |
| #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING) |
| QDebug operator<<(QDebug dbg, const QDate &date) |
| { |
| dbg.nospace() << "QDate(" << date.toString() << ')'; |
| return dbg.space(); |
| } |
| |
| QDebug operator<<(QDebug dbg, const QTime &time) |
| { |
| dbg.nospace() << "QTime(" << time.toString() << ')'; |
| return dbg.space(); |
| } |
| |
| QDebug operator<<(QDebug dbg, const QDateTime &date) |
| { |
| dbg.nospace() << "QDateTime(" << date.toString() << ')'; |
| return dbg.space(); |
| } |
| #endif |
| |
| #ifndef QT_BOOTSTRAPPED |
| |
| /*! |
| \internal |
| Gets the digit from a datetime. E.g. |
| |
| QDateTime var(QDate(2004, 02, 02)); |
| int digit = getDigit(var, Year); |
| // digit = 2004 |
| */ |
| |
| int QDateTimeParser::getDigit(const QDateTime &t, int index) const |
| { |
| if (index < 0 || index >= sectionNodes.size()) { |
| #ifndef QT_NO_DATESTRING |
| qWarning("QDateTimeParser::getDigit() Internal error (%s %d)", |
| qPrintable(t.toString()), index); |
| #else |
| qWarning("QDateTimeParser::getDigit() Internal error (%d)", index); |
| #endif |
| return -1; |
| } |
| const SectionNode &node = sectionNodes.at(index); |
| switch (node.type) { |
| case Hour24Section: case Hour12Section: return t.time().hour(); |
| case MinuteSection: return t.time().minute(); |
| case SecondSection: return t.time().second(); |
| case MSecSection: return t.time().msec(); |
| case YearSection2Digits: |
| case YearSection: return t.date().year(); |
| case MonthSection: return t.date().month(); |
| case DaySection: return t.date().day(); |
| case DayOfWeekSection: return t.date().day(); |
| case AmPmSection: return t.time().hour() > 11 ? 1 : 0; |
| |
| default: break; |
| } |
| |
| #ifndef QT_NO_DATESTRING |
| qWarning("QDateTimeParser::getDigit() Internal error 2 (%s %d)", |
| qPrintable(t.toString()), index); |
| #else |
| qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index); |
| #endif |
| return -1; |
| } |
| |
| /*! |
| \internal |
| Sets a digit in a datetime. E.g. |
| |
| QDateTime var(QDate(2004, 02, 02)); |
| int digit = getDigit(var, Year); |
| // digit = 2004 |
| setDigit(&var, Year, 2005); |
| digit = getDigit(var, Year); |
| // digit = 2005 |
| */ |
| |
| bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const |
| { |
| if (index < 0 || index >= sectionNodes.size()) { |
| #ifndef QT_NO_DATESTRING |
| qWarning("QDateTimeParser::setDigit() Internal error (%s %d %d)", |
| qPrintable(v.toString()), index, newVal); |
| #else |
| qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal); |
| #endif |
| return false; |
| } |
| const SectionNode &node = sectionNodes.at(index); |
| |
| int year, month, day, hour, minute, second, msec; |
| year = v.date().year(); |
| month = v.date().month(); |
| day = v.date().day(); |
| hour = v.time().hour(); |
| minute = v.time().minute(); |
| second = v.time().second(); |
| msec = v.time().msec(); |
| |
| switch (node.type) { |
| case Hour24Section: case Hour12Section: hour = newVal; break; |
| case MinuteSection: minute = newVal; break; |
| case SecondSection: second = newVal; break; |
| case MSecSection: msec = newVal; break; |
| case YearSection2Digits: |
| case YearSection: year = newVal; break; |
| case MonthSection: month = newVal; break; |
| case DaySection: |
| case DayOfWeekSection: |
| if (newVal > 31) { |
| // have to keep legacy behavior. setting the |
| // date to 32 should return false. Setting it |
| // to 31 for february should return true |
| return false; |
| } |
| day = newVal; |
| break; |
| case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break; |
| default: |
| qWarning("QDateTimeParser::setDigit() Internal error (%s)", |
| qPrintable(sectionName(node.type))); |
| break; |
| } |
| |
| if (!(node.type & (DaySection|DayOfWeekSection))) { |
| if (day < cachedDay) |
| day = cachedDay; |
| const int max = QDate(year, month, 1).daysInMonth(); |
| if (day > max) { |
| day = max; |
| } |
| } |
| if (QDate::isValid(year, month, day) && QTime::isValid(hour, minute, second, msec)) { |
| v = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec); |
| return true; |
| } |
| return false; |
| } |
| |
| |
| |
| /*! |
| \ |
| |
| Returns the absolute maximum for a section |
| */ |
| |
| int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const |
| { |
| const SectionNode &sn = sectionNode(s); |
| switch (sn.type) { |
| case Hour24Section: |
| case Hour12Section: return 23; // this is special-cased in |
| // parseSection. We want it to be |
| // 23 for the stepBy case. |
| case MinuteSection: |
| case SecondSection: return 59; |
| case MSecSection: return 999; |
| case YearSection2Digits: |
| case YearSection: return 9999; // sectionMaxSize will prevent |
| // people from typing in a larger |
| // number in count == 2 sections. |
| // stepBy() will work on real years anyway |
| case MonthSection: return 12; |
| case DaySection: |
| case DayOfWeekSection: return cur.isValid() ? cur.date().daysInMonth() : 31; |
| case AmPmSection: return 1; |
| default: break; |
| } |
| qWarning("QDateTimeParser::absoluteMax() Internal error (%s)", |
| qPrintable(sectionName(sn.type))); |
| return -1; |
| } |
| |
| /*! |
| \internal |
| |
| Returns the absolute minimum for a section |
| */ |
| |
| int QDateTimeParser::absoluteMin(int s) const |
| { |
| const SectionNode &sn = sectionNode(s); |
| switch (sn.type) { |
| case Hour24Section: |
| case Hour12Section: |
| case MinuteSection: |
| case SecondSection: |
| case MSecSection: |
| case YearSection2Digits: |
| case YearSection: return 0; |
| case MonthSection: |
| case DaySection: |
| case DayOfWeekSection: return 1; |
| case AmPmSection: return 0; |
| default: break; |
| } |
| qWarning("QDateTimeParser::absoluteMin() Internal error (%s, %0x)", |
| qPrintable(sectionName(sn.type)), sn.type); |
| return -1; |
| } |
| |
| /*! |
| \internal |
| |
| Returns the sectionNode for the Section \a s. |
| */ |
| |
| const QDateTimeParser::SectionNode &QDateTimeParser::sectionNode(int sectionIndex) const |
| { |
| if (sectionIndex < 0) { |
| switch (sectionIndex) { |
| case FirstSectionIndex: |
| return first; |
| case LastSectionIndex: |
| return last; |
| case NoSectionIndex: |
| return none; |
| } |
| } else if (sectionIndex < sectionNodes.size()) { |
| return sectionNodes.at(sectionIndex); |
| } |
| |
| qWarning("QDateTimeParser::sectionNode() Internal error (%d)", |
| sectionIndex); |
| return none; |
| } |
| |
| QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const |
| { |
| return sectionNode(sectionIndex).type; |
| } |
| |
| |
| /*! |
| \internal |
| |
| Returns the starting position for section \a s. |
| */ |
| |
| int QDateTimeParser::sectionPos(int sectionIndex) const |
| { |
| return sectionPos(sectionNode(sectionIndex)); |
| } |
| |
| int QDateTimeParser::sectionPos(const SectionNode &sn) const |
| { |
| switch (sn.type) { |
| case FirstSection: return 0; |
| case LastSection: return displayText().size() - 1; |
| default: break; |
| } |
| if (sn.pos == -1) { |
| qWarning("QDateTimeParser::sectionPos Internal error (%s)", qPrintable(sectionName(sn.type))); |
| return -1; |
| } |
| return sn.pos; |
| } |
| |
| |
| /*! |
| \internal helper function for parseFormat. removes quotes that are |
| not escaped and removes the escaping on those that are escaped |
| |
| */ |
| |
| static QString unquote(const QString &str) |
| { |
| const QChar quote(QLatin1Char('\'')); |
| const QChar slash(QLatin1Char('\\')); |
| const QChar zero(QLatin1Char('0')); |
| QString ret; |
| QChar status(zero); |
| const int max = str.size(); |
| for (int i=0; i<max; ++i) { |
| if (str.at(i) == quote) { |
| if (status != quote) { |
| status = quote; |
| } else if (!ret.isEmpty() && str.at(i - 1) == slash) { |
| ret[ret.size() - 1] = quote; |
| } else { |
| status = zero; |
| } |
| } else { |
| ret += str.at(i); |
| } |
| } |
| return ret; |
| } |
| /*! |
| \internal |
| |
| Parses the format \a newFormat. If successful, returns true and |
| sets up the format. Else keeps the old format and returns false. |
| |
| */ |
| |
| static inline int countRepeat(const QString &str, int index, int maxCount) |
| { |
| int count = 1; |
| const QChar ch(str.at(index)); |
| const int max = qMin(index + maxCount, str.size()); |
| while (index + count < max && str.at(index + count) == ch) { |
| ++count; |
| } |
| return count; |
| } |
| |
| static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote) |
| { |
| QString str(string.mid(from, size)); |
| if (lastQuote >= from) |
| str = unquote(str); |
| list->append(str); |
| } |
| |
| |
| bool QDateTimeParser::parseFormat(const QString &newFormat) |
| { |
| const QLatin1Char quote('\''); |
| const QLatin1Char slash('\\'); |
| const QLatin1Char zero('0'); |
| if (newFormat == displayFormat && !newFormat.isEmpty()) { |
| return true; |
| } |
| |
| QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData()); |
| |
| QVector<SectionNode> newSectionNodes; |
| Sections newDisplay = 0; |
| QStringList newSeparators; |
| int i, index = 0; |
| int add = 0; |
| QChar status(zero); |
| const int max = newFormat.size(); |
| int lastQuote = -1; |
| for (i = 0; i<max; ++i) { |
| if (newFormat.at(i) == quote) { |
| lastQuote = i; |
| ++add; |
| if (status != quote) { |
| status = quote; |
| } else if (newFormat.at(i - 1) != slash) { |
| status = zero; |
| } |
| } else if (status != quote) { |
| const char sect = newFormat.at(i).toLatin1(); |
| switch (sect) { |
| case 'H': |
| case 'h': |
| if (parserType != QVariant::Date) { |
| const Section hour = (sect == 'h') ? Hour12Section : Hour24Section; |
| const SectionNode sn = { hour, i - add, countRepeat(newFormat, i, 2) }; |
| newSectionNodes.append(sn); |
| appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); |
| i += sn.count - 1; |
| index = i + 1; |
| newDisplay |= hour; |
| } |
| break; |
| case 'm': |
| if (parserType != QVariant::Date) { |
| const SectionNode sn = { MinuteSection, i - add, countRepeat(newFormat, i, 2) }; |
| newSectionNodes.append(sn); |
| appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); |
| i += sn.count - 1; |
| index = i + 1; |
| newDisplay |= MinuteSection; |
| } |
| break; |
| case 's': |
| if (parserType != QVariant::Date) { |
| const SectionNode sn = { SecondSection, i - add, countRepeat(newFormat, i, 2) }; |
| newSectionNodes.append(sn); |
| appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); |
| i += sn.count - 1; |
| index = i + 1; |
| newDisplay |= SecondSection; |
| } |
| break; |
| |
| case 'z': |
| if (parserType != QVariant::Date) { |
| const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3 }; |
| newSectionNodes.append(sn); |
| appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); |
| i += sn.count - 1; |
| index = i + 1; |
| newDisplay |= MSecSection; |
| } |
| break; |
| case 'A': |
| case 'a': |
| if (parserType != QVariant::Date) { |
| const bool cap = (sect == 'A'); |
| const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0) }; |
| newSectionNodes.append(sn); |
| appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); |
| newDisplay |= AmPmSection; |
| if (i + 1 < newFormat.size() |
| && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) { |
| ++i; |
| } |
| index = i + 1; |
| } |
| break; |
| case 'y': |
| if (parserType != QVariant::Time) { |
| const int repeat = countRepeat(newFormat, i, 4); |
| if (repeat >= 2) { |
| const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits, |
| i - add, repeat == 4 ? 4 : 2 }; |
| newSectionNodes.append(sn); |
| appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); |
| i += sn.count - 1; |
| index = i + 1; |
| newDisplay |= sn.type; |
| } |
| } |
| break; |
| case 'M': |
| if (parserType != QVariant::Time) { |
| const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4) }; |
| newSectionNodes.append(sn); |
| newSeparators.append(unquote(newFormat.mid(index, i - index))); |
| i += sn.count - 1; |
| index = i + 1; |
| newDisplay |= MonthSection; |
| } |
| break; |
| case 'd': |
| if (parserType != QVariant::Time) { |
| const int repeat = countRepeat(newFormat, i, 4); |
| const SectionNode sn = { repeat >= 3 ? DayOfWeekSection : DaySection, i - add, repeat }; |
| newSectionNodes.append(sn); |
| appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); |
| i += sn.count - 1; |
| index = i + 1; |
| newDisplay |= sn.type; |
| } |
| break; |
| |
| default: |
| break; |
| } |
| } |
| } |
| if (newSectionNodes.isEmpty() && context == DateTimeEdit) { |
| return false; |
| } |
| |
| if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) { |
| const int max = newSectionNodes.size(); |
| for (int i=0; i<max; ++i) { |
| SectionNode &node = newSectionNodes[i]; |
| if (node.type == Hour12Section) |
| node.type = Hour24Section; |
| } |
| } |
| |
| if (index < newFormat.size()) { |
| appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote); |
| } else { |
| newSeparators.append(QString()); |
| } |
| |
| displayFormat = newFormat; |
| separators = newSeparators; |
| sectionNodes = newSectionNodes; |
| display = newDisplay; |
| last.pos = -1; |
| |
| // for (int i=0; i<sectionNodes.size(); ++i) { |
| // QDTPDEBUG << sectionName(sectionNodes.at(i).type) << sectionNodes.at(i).count; |
| // } |
| |
| QDTPDEBUG << newFormat << displayFormat; |
| QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData()); |
| |
| return true; |
| } |
| |
| /*! |
| \internal |
| |
| Returns the size of section \a s. |
| */ |
| |
| int QDateTimeParser::sectionSize(int sectionIndex) const |
| { |
| if (sectionIndex < 0) |
| return 0; |
| |
| if (sectionIndex >= sectionNodes.size()) { |
| qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex); |
| return -1; |
| } |
| if (sectionIndex == sectionNodes.size() - 1) { |
| return displayText().size() - sectionPos(sectionIndex) - separators.last().size(); |
| } else { |
| return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex) |
| - separators.at(sectionIndex + 1).size(); |
| } |
| } |
| |
| |
| int QDateTimeParser::sectionMaxSize(Section s, int count) const |
| { |
| #ifndef QT_NO_TEXTDATE |
| int mcount = 12; |
| #endif |
| |
| switch (s) { |
| case FirstSection: |
| case NoSection: |
| case LastSection: return 0; |
| |
| case AmPmSection: { |
| const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(), |
| getAmPmText(PmText, LowerCase).size()); |
| const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(), |
| getAmPmText(PmText, UpperCase).size()); |
| return qMin(4, qMin(lowerMax, upperMax)); |
| } |
| |
| case Hour24Section: |
| case Hour12Section: |
| case MinuteSection: |
| case SecondSection: |
| case DaySection: return 2; |
| case DayOfWeekSection: |
| #ifdef QT_NO_TEXTDATE |
| return 2; |
| #else |
| mcount = 7; |
| // fall through |
| #endif |
| case MonthSection: |
| if (count <= 2) |
| return 2; |
| |
| #ifdef QT_NO_TEXTDATE |
| return 2; |
| #else |
| { |
| int ret = 0; |
| const QLocale l = locale(); |
| for (int i=1; i<=mcount; ++i) { |
| const QString str = (s == MonthSection |
| ? l.monthName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat) |
| : l.dayName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat)); |
| ret = qMax(str.size(), ret); |
| } |
| return ret; |
| } |
| #endif |
| case MSecSection: return 3; |
| case YearSection: return 4; |
| case YearSection2Digits: return 2; |
| |
| case CalendarPopupSection: |
| case Internal: |
| case TimeSectionMask: |
| case DateSectionMask: |
| qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s", |
| sectionName(s).toLatin1().constData()); |
| |
| case NoSectionIndex: |
| case FirstSectionIndex: |
| case LastSectionIndex: |
| case CalendarPopupIndex: |
| // these cases can't happen |
| break; |
| } |
| return -1; |
| } |
| |
| |
| int QDateTimeParser::sectionMaxSize(int index) const |
| { |
| const SectionNode &sn = sectionNode(index); |
| return sectionMaxSize(sn.type, sn.count); |
| } |
| |
| /*! |
| \internal |
| |
| Returns the text of section \a s. This function operates on the |
| arg text rather than edit->text(). |
| */ |
| |
| |
| QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const |
| { |
| const SectionNode &sn = sectionNode(sectionIndex); |
| switch (sn.type) { |
| case NoSectionIndex: |
| case FirstSectionIndex: |
| case LastSectionIndex: |
| return QString(); |
| default: break; |
| } |
| |
| return text.mid(index, sectionSize(sectionIndex)); |
| } |
| |
| QString QDateTimeParser::sectionText(int sectionIndex) const |
| { |
| const SectionNode &sn = sectionNode(sectionIndex); |
| switch (sn.type) { |
| case NoSectionIndex: |
| case FirstSectionIndex: |
| case LastSectionIndex: |
| return QString(); |
| default: break; |
| } |
| |
| return displayText().mid(sn.pos, sectionSize(sectionIndex)); |
| } |
| |
| |
| #ifndef QT_NO_TEXTDATE |
| /*! |
| \internal:skipToNextSection |
| |
| Parses the part of \a text that corresponds to \a s and returns |
| the value of that field. Sets *stateptr to the right state if |
| stateptr != 0. |
| */ |
| |
| int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex, |
| QString &text, int &cursorPosition, int index, |
| State &state, int *usedptr) const |
| { |
| state = Invalid; |
| int num = 0; |
| const SectionNode &sn = sectionNode(sectionIndex); |
| if ((sn.type & Internal) == Internal) { |
| qWarning("QDateTimeParser::parseSection Internal error (%s %d)", |
| qPrintable(sectionName(sn.type)), sectionIndex); |
| return -1; |
| } |
| |
| const int sectionmaxsize = sectionMaxSize(sectionIndex); |
| QString sectiontext = text.mid(index, sectionmaxsize); |
| int sectiontextSize = sectiontext.size(); |
| |
| QDTPDEBUG << "sectionValue for" << sectionName(sn.type) |
| << "with text" << text << "and st" << sectiontext |
| << text.mid(index, sectionmaxsize) |
| << index; |
| |
| int used = 0; |
| switch (sn.type) { |
| case AmPmSection: { |
| const int ampm = findAmPm(sectiontext, sectionIndex, &used); |
| switch (ampm) { |
| case AM: // sectiontext == AM |
| case PM: // sectiontext == PM |
| num = ampm; |
| state = Acceptable; |
| break; |
| case PossibleAM: // sectiontext => AM |
| case PossiblePM: // sectiontext => PM |
| num = ampm - 2; |
| state = Intermediate; |
| break; |
| case PossibleBoth: // sectiontext => AM|PM |
| num = 0; |
| state = Intermediate; |
| break; |
| case Neither: |
| state = Invalid; |
| QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1"; |
| break; |
| default: |
| QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm); |
| break; |
| } |
| if (state != Invalid) { |
| QString str = text; |
| text.replace(index, used, sectiontext.left(used)); |
| } |
| break; } |
| case MonthSection: |
| case DayOfWeekSection: |
| if (sn.count >= 3) { |
| if (sn.type == MonthSection) { |
| int min = 1; |
| const QDate minDate = getMinimum().date(); |
| if (currentValue.date().year() == minDate.year()) { |
| min = minDate.month(); |
| } |
| num = findMonth(sectiontext.toLower(), min, sectionIndex, §iontext, &used); |
| } else { |
| num = findDay(sectiontext.toLower(), 1, sectionIndex, §iontext, &used); |
| } |
| |
| if (num != -1) { |
| state = (used == sectiontext.size() ? Acceptable : Intermediate); |
| QString str = text; |
| text.replace(index, used, sectiontext.left(used)); |
| } else { |
| state = Intermediate; |
| } |
| break; } |
| // fall through |
| case DaySection: |
| case YearSection: |
| case YearSection2Digits: |
| case Hour12Section: |
| case Hour24Section: |
| case MinuteSection: |
| case SecondSection: |
| case MSecSection: { |
| if (sectiontextSize == 0) { |
| num = 0; |
| used = 0; |
| state = Intermediate; |
| } else { |
| const int absMax = absoluteMax(sectionIndex); |
| QLocale loc; |
| bool ok = true; |
| int last = -1; |
| used = -1; |
| |
| QString digitsStr(sectiontext); |
| for (int i = 0; i < sectiontextSize; ++i) { |
| if (digitsStr.at(i).isSpace()) { |
| sectiontextSize = i; |
| break; |
| } |
| } |
| |
| const int max = qMin(sectionmaxsize, sectiontextSize); |
| for (int digits = max; digits >= 1; --digits) { |
| digitsStr.truncate(digits); |
| int tmp = (int)loc.toUInt(digitsStr, &ok, 10); |
| if (ok && sn.type == Hour12Section) { |
| if (tmp > 12) { |
| tmp = -1; |
| ok = false; |
| } else if (tmp == 12) { |
| tmp = 0; |
| } |
| } |
| if (ok && tmp <= absMax) { |
| QDTPDEBUG << sectiontext.left(digits) << tmp << digits; |
| last = tmp; |
| used = digits; |
| break; |
| } |
| } |
| |
| if (last == -1) { |
| QChar first(sectiontext.at(0)); |
| if (separators.at(sectionIndex + 1).startsWith(first)) { |
| used = 0; |
| state = Intermediate; |
| } else { |
| state = Invalid; |
| QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok; |
| } |
| } else { |
| num += last; |
| const FieldInfo fi = fieldInfo(sectionIndex); |
| const bool done = (used == sectionmaxsize); |
| if (!done && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002 |
| for (int i=used; i<sectionmaxsize; ++i) { |
| num *= 10; |
| } |
| } |
| const int absMin = absoluteMin(sectionIndex); |
| if (num < absMin) { |
| state = done ? Invalid : Intermediate; |
| if (done) |
| QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absMin; |
| } else if (num > absMax) { |
| state = Intermediate; |
| } else if (!done && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) { |
| if (skipToNextSection(sectionIndex, currentValue, digitsStr)) { |
| state = Acceptable; |
| const int missingZeroes = sectionmaxsize - digitsStr.size(); |
| text.insert(index, QString().fill(QLatin1Char('0'), missingZeroes)); |
| used = sectionmaxsize; |
| cursorPosition += missingZeroes; |
| } else { |
| state = Intermediate;; |
| } |
| } else { |
| state = Acceptable; |
| } |
| } |
| } |
| break; } |
| default: |
| qWarning("QDateTimeParser::parseSection Internal error (%s %d)", |
| qPrintable(sectionName(sn.type)), sectionIndex); |
| return -1; |
| } |
| |
| if (usedptr) |
| *usedptr = used; |
| |
| return (state != Invalid ? num : -1); |
| } |
| #endif // QT_NO_TEXTDATE |
| |
| #ifndef QT_NO_DATESTRING |
| /*! |
| \internal |
| */ |
| |
| QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPosition, |
| const QDateTime ¤tValue, bool fixup) const |
| { |
| const QDateTime minimum = getMinimum(); |
| const QDateTime maximum = getMaximum(); |
| |
| State state = Acceptable; |
| |
| QDateTime newCurrentValue; |
| int pos = 0; |
| bool conflicts = false; |
| const int sectionNodesCount = sectionNodes.size(); |
| |
| QDTPDEBUG << "parse" << input; |
| { |
| int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits; |
| getDateFromJulianDay(currentValue.date().toJulianDay(), &year, &month, &day); |
| year2digits = year % 100; |
| hour = currentValue.time().hour(); |
| hour12 = -1; |
| minute = currentValue.time().minute(); |
| second = currentValue.time().second(); |
| msec = currentValue.time().msec(); |
| dayofweek = currentValue.date().dayOfWeek(); |
| |
| ampm = -1; |
| Sections isSet = NoSection; |
| int num; |
| State tmpstate; |
| |
| for (int index=0; state != Invalid && index<sectionNodesCount; ++index) { |
| if (QStringRef(&input, pos, separators.at(index).size()) != separators.at(index)) { |
| QDTPDEBUG << "invalid because" << input.mid(pos, separators.at(index).size()) |
| << "!=" << separators.at(index) |
| << index << pos << currentSectionIndex; |
| state = Invalid; |
| goto end; |
| } |
| pos += separators.at(index).size(); |
| sectionNodes[index].pos = pos; |
| int *current = 0; |
| const SectionNode sn = sectionNodes.at(index); |
| int used; |
| |
| num = parseSection(currentValue, index, input, cursorPosition, pos, tmpstate, &used); |
| QDTPDEBUG << "sectionValue" << sectionName(sectionType(index)) << input |
| << "pos" << pos << "used" << used << stateName(tmpstate); |
| if (fixup && tmpstate == Intermediate && used < sn.count) { |
| const FieldInfo fi = fieldInfo(index); |
| if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) { |
| const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0')); |
| input.replace(pos, used, newText); |
| used = sn.count; |
| } |
| } |
| pos += qMax(0, used); |
| |
| state = qMin<State>(state, tmpstate); |
| if (state == Intermediate && context == FromString) { |
| state = Invalid; |
| break; |
| } |
| |
| QDTPDEBUG << index << sectionName(sectionType(index)) << "is set to" |
| << pos << "state is" << stateName(state); |
| |
| |
| if (state != Invalid) { |
| switch (sn.type) { |
| case Hour24Section: current = &hour; break; |
| case Hour12Section: current = &hour12; break; |
| case MinuteSection: current = &minute; break; |
| case SecondSection: current = &second; break; |
| case MSecSection: current = &msec; break; |
| case YearSection: current = &year; break; |
| case YearSection2Digits: current = &year2digits; break; |
| case MonthSection: current = &month; break; |
| case DayOfWeekSection: current = &dayofweek; break; |
| case DaySection: current = &day; num = qMax<int>(1, num); break; |
| case AmPmSection: current = &m; break; |
| default: |
| qWarning("QDateTimeParser::parse Internal error (%s)", |
| qPrintable(sectionName(sn.type))); |
| break; |
| } |
| if (!current) { |
| qWarning("QDateTimeParser::parse Internal error 2"); |
| return StateNode(); |
| } |
| if (isSet & sn.type && *current != num) { |
| QDTPDEBUG << "CONFLICT " << sectionName(sn.type) << *current << num; |
| conflicts = true; |
| if (index != currentSectionIndex || num == -1) { |
| continue; |
| } |
| } |
| if (num != -1) |
| *current = num; |
| isSet |= sn.type; |
| } |
| } |
| |
| if (state != Invalid && QStringRef(&input, pos, input.size() - pos) != separators.last()) { |
| QDTPDEBUG << "invalid because" << input.mid(pos) |
| << "!=" << separators.last() << pos; |
| state = Invalid; |
| } |
| |
| if (state != Invalid) { |
| if (parserType != QVariant::Time) { |
| if (year % 100 != year2digits) { |
| switch (isSet & (YearSection2Digits|YearSection)) { |
| case YearSection2Digits: |
| year = (year / 100) * 100; |
| year += year2digits; |
| break; |
| case ((uint)YearSection2Digits|(uint)YearSection): { |
| conflicts = true; |
| const SectionNode &sn = sectionNode(currentSectionIndex); |
| if (sn.type == YearSection2Digits) { |
| year = (year / 100) * 100; |
| year += year2digits; |
| } |
| break; } |
| default: |
| break; |
| } |
| } |
| |
| const QDate date(year, month, day); |
| const int diff = dayofweek - date.dayOfWeek(); |
| if (diff != 0 && state == Acceptable && isSet & DayOfWeekSection) { |
| conflicts = isSet & DaySection; |
| const SectionNode &sn = sectionNode(currentSectionIndex); |
| if (sn.type == DayOfWeekSection || currentSectionIndex == -1) { |
| // dayofweek should be preferred |
| day += diff; |
| if (day <= 0) { |
| day += 7; |
| } else if (day > date.daysInMonth()) { |
| day -= 7; |
| } |
| QDTPDEBUG << year << month << day << dayofweek |
| << diff << QDate(year, month, day).dayOfWeek(); |
| } |
| } |
| bool needfixday = false; |
| if (sectionType(currentSectionIndex) & (DaySection|DayOfWeekSection)) { |
| cachedDay = day; |
| } else if (cachedDay > day) { |
| day = cachedDay; |
| needfixday = true; |
| } |
| |
| if (!QDate::isValid(year, month, day)) { |
| if (day < 32) { |
| cachedDay = day; |
| } |
| if (day > 28 && QDate::isValid(year, month, 1)) { |
| needfixday = true; |
| } |
| } |
| if (needfixday) { |
| if (context == FromString) { |
| state = Invalid; |
| goto end; |
| } |
| if (state == Acceptable && fixday) { |
| day = qMin<int>(day, QDate(year, month, 1).daysInMonth()); |
| |
| const QLocale loc = locale(); |
| for (int i=0; i<sectionNodesCount; ++i) { |
| if (sectionType(i) & (DaySection|DayOfWeekSection)) { |
| input.replace(sectionPos(i), sectionSize(i), loc.toString(day)); |
| } |
| } |
| } else { |
| state = qMin(Intermediate, state); |
| } |
| } |
| } |
| |
| if (parserType != QVariant::Date) { |
| if (isSet & Hour12Section) { |
| const bool hasHour = isSet & Hour24Section; |
| if (ampm == -1) { |
| if (hasHour) { |
| ampm = (hour < 12 ? 0 : 1); |
| } else { |
| ampm = 0; // no way to tell if this is am or pm so I assume am |
| } |
| } |
| hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12); |
| if (!hasHour) { |
| hour = hour12; |
| } else if (hour != hour12) { |
| conflicts = true; |
| } |
| } else if (ampm != -1) { |
| if (!(isSet & (Hour24Section))) { |
| hour = (12 * ampm); // special case. Only ap section |
| } else if ((ampm == 0) != (hour < 12)) { |
| conflicts = true; |
| } |
| } |
| |
| } |
| |
| newCurrentValue = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec); |
| QDTPDEBUG << year << month << day << hour << minute << second << msec; |
| } |
| QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(), |
| newCurrentValue.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(), |
| stateName(state).toLatin1().constData()); |
| } |
| end: |
| if (newCurrentValue.isValid()) { |
| if (context != FromString && state != Invalid && newCurrentValue < minimum) { |
| const QLatin1Char space(' '); |
| if (newCurrentValue >= minimum) |
| qWarning("QDateTimeParser::parse Internal error 3 (%s %s)", |
| qPrintable(newCurrentValue.toString()), qPrintable(minimum.toString())); |
| |
| bool done = false; |
| state = Invalid; |
| for (int i=0; i<sectionNodesCount && !done; ++i) { |
| const SectionNode &sn = sectionNodes.at(i); |
| QString t = sectionText(input, i, sn.pos).toLower(); |
| if ((t.size() < sectionMaxSize(i) && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric)) |
| || t.contains(space)) { |
| switch (sn.type) { |
| case AmPmSection: |
| switch (findAmPm(t, i)) { |
| case AM: |
| case PM: |
| state = Acceptable; |
| done = true; |
| break; |
| case Neither: |
| state = Invalid; |
| done = true; |
| break; |
| case PossibleAM: |
| case PossiblePM: |
| case PossibleBoth: { |
| const QDateTime copy(newCurrentValue.addSecs(12 * 60 * 60)); |
| if (copy >= minimum && copy <= maximum) { |
| state = Intermediate; |
| done = true; |
| } |
| break; } |
| } |
| case MonthSection: |
| if (sn.count >= 3) { |
| int tmp = newCurrentValue.date().month(); |
| // I know the first possible month makes the date too early |
| while ((tmp = findMonth(t, tmp + 1, i)) != -1) { |
| const QDateTime copy(newCurrentValue.addMonths(tmp - newCurrentValue.date().month())); |
| if (copy >= minimum && copy <= maximum) |
| break; // break out of while |
| } |
| if (tmp == -1) { |
| break; |
| } |
| state = Intermediate; |
| done = true; |
| break; |
| } |
| // fallthrough |
| default: { |
| int toMin; |
| int toMax; |
| |
| if (sn.type & TimeSectionMask) { |
| if (newCurrentValue.daysTo(minimum) != 0) { |
| break; |
| } |
| toMin = newCurrentValue.time().msecsTo(minimum.time()); |
| if (newCurrentValue.daysTo(maximum) > 0) { |
| toMax = -1; // can't get to max |
| } else { |
| toMax = newCurrentValue.time().msecsTo(maximum.time()); |
| } |
| } else { |
| toMin = newCurrentValue.daysTo(minimum); |
| toMax = newCurrentValue.daysTo(maximum); |
| } |
| const int maxChange = QDateTimeParser::maxChange(i); |
| if (toMin > maxChange) { |
| QDTPDEBUG << "invalid because toMin > maxChange" << toMin |
| << maxChange << t << newCurrentValue << minimum; |
| state = Invalid; |
| done = true; |
| break; |
| } else if (toMax > maxChange) { |
| toMax = -1; // can't get to max |
| } |
| |
| const int min = getDigit(minimum, i); |
| if (min == -1) { |
| qWarning("QDateTimeParser::parse Internal error 4 (%s)", |
| qPrintable(sectionName(sn.type))); |
| state = Invalid; |
| done = true; |
| break; |
| } |
| |
| int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, newCurrentValue); |
| int pos = cursorPosition - sn.pos; |
| if (pos < 0 || pos >= t.size()) |
| pos = -1; |
| if (!potentialValue(t.simplified(), min, max, i, newCurrentValue, pos)) { |
| QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max |
| << sectionName(sn.type) << "returned" << toMax << toMin << pos; |
| state = Invalid; |
| done = true; |
| break; |
| } |
| state = Intermediate; |
| done = true; |
| break; } |
| } |
| } |
| } |
| } else { |
| if (context == FromString) { |
| // optimization |
| Q_ASSERT(getMaximum().date().toJulianDay() == 4642999); |
| if (newCurrentValue.date().toJulianDay() > 4642999) |
| state = Invalid; |
| } else { |
| if (newCurrentValue > getMaximum()) |
| state = Invalid; |
| } |
| |
| QDTPDEBUG << "not checking intermediate because newCurrentValue is" << newCurrentValue << getMinimum() << getMaximum(); |
| } |
| } |
| StateNode node; |
| node.input = input; |
| node.state = state; |
| node.conflicts = conflicts; |
| node.value = newCurrentValue.toTimeSpec(spec); |
| text = input; |
| return node; |
| } |
| #endif // QT_NO_DATESTRING |
| |
| #ifndef QT_NO_TEXTDATE |
| /*! |
| \internal finds the first possible monthname that \a str1 can |
| match. Starting from \a index; str should already by lowered |
| */ |
| |
| int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex, |
| QString *usedMonth, int *used) const |
| { |
| int bestMatch = -1; |
| int bestCount = 0; |
| if (!str1.isEmpty()) { |
| const SectionNode &sn = sectionNode(sectionIndex); |
| if (sn.type != MonthSection) { |
| qWarning("QDateTimeParser::findMonth Internal error"); |
| return -1; |
| } |
| |
| QLocale::FormatType type = sn.count == 3 ? QLocale::ShortFormat : QLocale::LongFormat; |
| QLocale l = locale(); |
| |
| for (int month=startMonth; month<=12; ++month) { |
| QString str2 = l.monthName(month, type).toLower(); |
| |
| if (str1.startsWith(str2)) { |
| if (used) { |
| QDTPDEBUG << "used is set to" << str2.size(); |
| *used = str2.size(); |
| } |
| if (usedMonth) |
| *usedMonth = l.monthName(month, type); |
| |
| return month; |
| } |
| if (context == FromString) |
| continue; |
| |
| const int limit = qMin(str1.size(), str2.size()); |
| |
| QDTPDEBUG << "limit is" << limit << str1 << str2; |
| bool equal = true; |
| for (int i=0; i<limit; ++i) { |
| if (str1.at(i) != str2.at(i)) { |
| equal = false; |
| if (i > bestCount) { |
| bestCount = i; |
| bestMatch = month; |
| } |
| break; |
| } |
| } |
| if (equal) { |
| if (used) |
| *used = limit; |
| if (usedMonth) |
| *usedMonth = l.monthName(month, type); |
| return month; |
| } |
| } |
| if (usedMonth && bestMatch != -1) |
| *usedMonth = l.monthName(bestMatch, type); |
| } |
| if (used) { |
| QDTPDEBUG << "used is set to" << bestCount; |
| *used = bestCount; |
| } |
| return bestMatch; |
| } |
| |
| int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const |
| { |
| int bestMatch = -1; |
| int bestCount = 0; |
| if (!str1.isEmpty()) { |
| const SectionNode &sn = sectionNode(sectionIndex); |
| if (!(sn.type & (DaySection|DayOfWeekSection))) { |
| qWarning("QDateTimeParser::findDay Internal error"); |
| return -1; |
| } |
| const QLocale l = locale(); |
| for (int day=startDay; day<=7; ++day) { |
| const QString str2 = l.dayName(day, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat); |
| |
| if (str1.startsWith(str2.toLower())) { |
| if (used) |
| *used = str2.size(); |
| if (usedDay) { |
| *usedDay = str2; |
| } |
| return day; |
| } |
| if (context == FromString) |
| continue; |
| |
| const int limit = qMin(str1.size(), str2.size()); |
| bool found = true; |
| for (int i=0; i<limit; ++i) { |
| if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) { |
| if (i > bestCount) { |
| bestCount = i; |
| bestMatch = day; |
| } |
| found = false; |
| break; |
| } |
| |
| } |
| if (found) { |
| if (used) |
| *used = limit; |
| if (usedDay) |
| *usedDay = str2; |
| |
| return day; |
| } |
| } |
| if (usedDay && bestMatch != -1) { |
| *usedDay = l.dayName(bestMatch, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat); |
| } |
| } |
| if (used) |
| *used = bestCount; |
| |
| return bestMatch; |
| } |
| #endif // QT_NO_TEXTDATE |
| |
| /*! |
| \internal |
| |
| returns |
| 0 if str == QDateTimeEdit::tr("AM") |
| 1 if str == QDateTimeEdit::tr("PM") |
| 2 if str can become QDateTimeEdit::tr("AM") |
| 3 if str can become QDateTimeEdit::tr("PM") |
| 4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM") |
| -1 can't become anything sensible |
| |
| */ |
| |
| int QDateTimeParser::findAmPm(QString &str, int index, int *used) const |
| { |
| const SectionNode &s = sectionNode(index); |
| if (s.type != AmPmSection) { |
| qWarning("QDateTimeParser::findAmPm Internal error"); |
| return -1; |
| } |
| if (used) |
| *used = str.size(); |
| if (str.trimmed().isEmpty()) { |
| return PossibleBoth; |
| } |
| const QLatin1Char space(' '); |
| int size = sectionMaxSize(index); |
| |
| enum { |
| amindex = 0, |
| pmindex = 1 |
| }; |
| QString ampm[2]; |
| ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase); |
| ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase); |
| for (int i=0; i<2; ++i) |
| ampm[i].truncate(size); |
| |
| QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1]; |
| |
| if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) { |
| str = ampm[amindex]; |
| return AM; |
| } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) { |
| str = ampm[pmindex]; |
| return PM; |
| } else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) { |
| return Neither; |
| } |
| size = qMin(size, str.size()); |
| |
| bool broken[2] = {false, false}; |
| for (int i=0; i<size; ++i) { |
| if (str.at(i) != space) { |
| for (int j=0; j<2; ++j) { |
| if (!broken[j]) { |
| int index = ampm[j].indexOf(str.at(i)); |
| QDTPDEBUG << "looking for" << str.at(i) |
| << "in" << ampm[j] << "and got" << index; |
| if (index == -1) { |
| if (str.at(i).category() == QChar::Letter_Uppercase) { |
| index = ampm[j].indexOf(str.at(i).toLower()); |
| QDTPDEBUG << "trying with" << str.at(i).toLower() |
| << "in" << ampm[j] << "and got" << index; |
| } else if (str.at(i).category() == QChar::Letter_Lowercase) { |
| index = ampm[j].indexOf(str.at(i).toUpper()); |
| QDTPDEBUG << "trying with" << str.at(i).toUpper() |
| << "in" << ampm[j] << "and got" << index; |
| } |
| if (index == -1) { |
| broken[j] = true; |
| if (broken[amindex] && broken[pmindex]) { |
| QDTPDEBUG << str << "didn't make it"; |
| return Neither; |
| } |
| continue; |
| } else { |
| str[i] = ampm[j].at(index); // fix case |
| } |
| } |
| ampm[j].remove(index, 1); |
| } |
| } |
| } |
| } |
| if (!broken[pmindex] && !broken[amindex]) |
| return PossibleBoth; |
| return (!broken[amindex] ? PossibleAM : PossiblePM); |
| } |
| |
| /*! |
| \internal |
| Max number of units that can be changed by this section. |
| */ |
| |
| int QDateTimeParser::maxChange(int index) const |
| { |
| const SectionNode &sn = sectionNode(index); |
| switch (sn.type) { |
| // Time. unit is msec |
| case MSecSection: return 999; |
| case SecondSection: return 59 * 1000; |
| case MinuteSection: return 59 * 60 * 1000; |
| case Hour24Section: case Hour12Section: return 59 * 60 * 60 * 1000; |
| |
| // Date. unit is day |
| case DayOfWeekSection: return 7; |
| case DaySection: return 30; |
| case MonthSection: return 365 - 31; |
| case YearSection: return 9999 * 365; |
| case YearSection2Digits: return 100 * 365; |
| default: |
| qWarning("QDateTimeParser::maxChange() Internal error (%s)", |
| qPrintable(sectionName(sectionType(index)))); |
| } |
| |
| return -1; |
| } |
| |
| QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const |
| { |
| FieldInfo ret = 0; |
| const SectionNode &sn = sectionNode(index); |
| const Section s = sn.type; |
| switch (s) { |
| case MSecSection: |
| ret |= Fraction; |
| // fallthrough |
| case SecondSection: |
| case MinuteSection: |
| case Hour24Section: |
| case Hour12Section: |
| case YearSection: |
| case YearSection2Digits: |
| ret |= Numeric; |
| if (s != YearSection) { |
| ret |= AllowPartial; |
| } |
| if (sn.count != 1) { |
| ret |= FixedWidth; |
| } |
| break; |
| case MonthSection: |
| case DaySection: |
| switch (sn.count) { |
| case 2: |
| ret |= FixedWidth; |
| // fallthrough |
| case 1: |
| ret |= (Numeric|AllowPartial); |
| break; |
| } |
| break; |
| case DayOfWeekSection: |
| if (sn.count == 3) |
| ret |= FixedWidth; |
| break; |
| case AmPmSection: |
| ret |= FixedWidth; |
| break; |
| default: |
| qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)", |
| index, qPrintable(sectionName(sn.type)), sn.count); |
| break; |
| } |
| return ret; |
| } |
| |
| /*! |
| \internal Get a number that str can become which is between min |
| and max or -1 if this is not possible. |
| */ |
| |
| |
| QString QDateTimeParser::sectionFormat(int index) const |
| { |
| const SectionNode &sn = sectionNode(index); |
| return sectionFormat(sn.type, sn.count); |
| } |
| |
| QString QDateTimeParser::sectionFormat(Section s, int count) const |
| { |
| QChar fillChar; |
| switch (s) { |
| case AmPmSection: return count == 1 ? QLatin1String("AP") : QLatin1String("ap"); |
| case MSecSection: fillChar = QLatin1Char('z'); break; |
| case SecondSection: fillChar = QLatin1Char('s'); break; |
| case MinuteSection: fillChar = QLatin1Char('m'); break; |
| case Hour24Section: fillChar = QLatin1Char('H'); break; |
| case Hour12Section: fillChar = QLatin1Char('h'); break; |
| case DayOfWeekSection: |
| case DaySection: fillChar = QLatin1Char('d'); break; |
| case MonthSection: fillChar = QLatin1Char('M'); break; |
| case YearSection2Digits: |
| case YearSection: fillChar = QLatin1Char('y'); break; |
| default: |
| qWarning("QDateTimeParser::sectionFormat Internal error (%s)", |
| qPrintable(sectionName(s))); |
| return QString(); |
| } |
| if (fillChar.isNull()) { |
| qWarning("QDateTimeParser::sectionFormat Internal error 2"); |
| return QString(); |
| } |
| |
| QString str; |
| str.fill(fillChar, count); |
| return str; |
| } |
| |
| |
| /*! \internal Returns true if str can be modified to represent a |
| number that is within min and max. |
| */ |
| |
| bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index, |
| const QDateTime ¤tValue, int insert) const |
| { |
| if (str.isEmpty()) { |
| return true; |
| } |
| const int size = sectionMaxSize(index); |
| int val = (int)locale().toUInt(str); |
| const SectionNode &sn = sectionNode(index); |
| if (sn.type == YearSection2Digits) { |
| val += currentValue.date().year() - (currentValue.date().year() % 100); |
| } |
| if (val >= min && val <= max && str.size() == size) { |
| return true; |
| } else if (val > max) { |
| return false; |
| } else if (str.size() == size && val < min) { |
| return false; |
| } |
| |
| const int len = size - str.size(); |
| for (int i=0; i<len; ++i) { |
| for (int j=0; j<10; ++j) { |
| if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) { |
| return true; |
| } else if (insert >= 0) { |
| QString tmp = str; |
| tmp.insert(insert, QLatin1Char('0' + j)); |
| if (potentialValue(tmp, min, max, index, currentValue, insert)) |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| bool QDateTimeParser::skipToNextSection(int index, const QDateTime ¤t, const QString &text) const |
| { |
| Q_ASSERT(current >= getMinimum() && current <= getMaximum()); |
| |
| const SectionNode &node = sectionNode(index); |
| Q_ASSERT(text.size() < sectionMaxSize(index)); |
| |
| const QDateTime maximum = getMaximum(); |
| const QDateTime minimum = getMinimum(); |
| QDateTime tmp = current; |
| int min = absoluteMin(index); |
| setDigit(tmp, index, min); |
| if (tmp < minimum) { |
| min = getDigit(minimum, index); |
| } |
| |
| int max = absoluteMax(index, current); |
| setDigit(tmp, index, max); |
| if (tmp > maximum) { |
| max = getDigit(maximum, index); |
| } |
| int pos = cursorPosition() - node.pos; |
| if (pos < 0 || pos >= text.size()) |
| pos = -1; |
| |
| const bool potential = potentialValue(text, min, max, index, current, pos); |
| return !potential; |
| |
| /* If the value potentially can become another valid entry we |
| * don't want to skip to the next. E.g. In a M field (month |
| * without leading 0 if you type 1 we don't want to autoskip but |
| * if you type 3 we do |
| */ |
| } |
| |
| /*! |
| \internal |
| For debugging. Returns the name of the section \a s. |
| */ |
| |
| QString QDateTimeParser::sectionName(int s) const |
| { |
| switch (s) { |
| case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection"); |
| case QDateTimeParser::DaySection: return QLatin1String("DaySection"); |
| case QDateTimeParser::DayOfWeekSection: return QLatin1String("DayOfWeekSection"); |
| case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section"); |
| case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section"); |
| case QDateTimeParser::MSecSection: return QLatin1String("MSecSection"); |
| case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection"); |
| case QDateTimeParser::MonthSection: return QLatin1String("MonthSection"); |
| case QDateTimeParser::SecondSection: return QLatin1String("SecondSection"); |
| case QDateTimeParser::YearSection: return QLatin1String("YearSection"); |
| case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits"); |
| case QDateTimeParser::NoSection: return QLatin1String("NoSection"); |
| case QDateTimeParser::FirstSection: return QLatin1String("FirstSection"); |
| case QDateTimeParser::LastSection: return QLatin1String("LastSection"); |
| default: return QLatin1String("Unknown section ") + QString::number(s); |
| } |
| } |
| |
| /*! |
| \internal |
| For debugging. Returns the name of the state \a s. |
| */ |
| |
| QString QDateTimeParser::stateName(int s) const |
| { |
| switch (s) { |
| case Invalid: return QLatin1String("Invalid"); |
| case Intermediate: return QLatin1String("Intermediate"); |
| case Acceptable: return QLatin1String("Acceptable"); |
| default: return QLatin1String("Unknown state ") + QString::number(s); |
| } |
| } |
| |
| #ifndef QT_NO_DATESTRING |
| bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const |
| { |
| QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN); |
| QString text = t; |
| int copy = -1; |
| const StateNode tmp = parse(text, copy, val, false); |
| if (tmp.state != Acceptable || tmp.conflicts) { |
| return false; |
| } |
| if (time) { |
| const QTime t = tmp.value.time(); |
| if (!t.isValid()) { |
| return false; |
| } |
| *time = t; |
| } |
| |
| if (date) { |
| const QDate d = tmp.value.date(); |
| if (!d.isValid()) { |
| return false; |
| } |
| *date = d; |
| } |
| return true; |
| } |
| #endif // QT_NO_DATESTRING |
| |
| QDateTime QDateTimeParser::getMinimum() const |
| { |
| return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec); |
| } |
| |
| QDateTime QDateTimeParser::getMaximum() const |
| { |
| return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec); |
| } |
| |
| QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const |
| { |
| if (ap == AmText) { |
| return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am")); |
| } else { |
| return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm")); |
| } |
| } |
| |
| /* |
| \internal |
| |
| I give arg2 preference because arg1 is always a QDateTime. |
| */ |
| |
| bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2) |
| { |
| return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count); |
| } |
| |
| |
| #endif // QT_BOOTSTRAPPED |
| |
| QT_END_NAMESPACE |