00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qplatformdefs.h"
00025 #include "private/qdatetime_p.h"
00026
00027 #include "qdatastream.h"
00028 #include "qset.h"
00029 #include "qlocale.h"
00030 #include "qdatetime.h"
00031 #include "qregexp.h"
00032 #include "qdebug.h"
00033 #if defined(Q_OS_WIN32)
00034 #include <windows.h>
00035 #endif
00036 #ifndef Q_WS_WIN
00037 #include <locale.h>
00038 #endif
00039
00040 #include <time.h>
00041
00042
00043 #if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM)
00044 # define QDTPDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__)
00045 # define QDTPDEBUGN qDebug
00046 #else
00047 # define QDTPDEBUG if (false) qDebug()
00048 # define QDTPDEBUGN if (false) qDebug
00049 #endif
00050
00051 #if defined(Q_WS_MAC)
00052 #include <private/qcore_mac_p.h>
00053 extern QString qt_mac_from_pascal_string(const Str255);
00054 #endif
00055
00056 enum {
00057 FIRST_YEAR = -4713,
00058 FIRST_MONTH = 1,
00059 FIRST_DAY = 2,
00060 SECS_PER_DAY = 86400,
00061 MSECS_PER_DAY = 86400000,
00062 SECS_PER_HOUR = 3600,
00063 MSECS_PER_HOUR = 3600000,
00064 SECS_PER_MIN = 60,
00065 MSECS_PER_MIN = 60000
00066 };
00067
00068 static inline QDate strictDate(int y, int m, int d)
00069 {
00070 QDate result;
00071 result.setDate(y, m, d);
00072 return result;
00073 }
00074
00075 static inline QDate fixedDate(int y, int m, int d)
00076 {
00077 QDate result(strictDate(y, m, 1));
00078 result.setDate(y, m, qMin(d, result.daysInMonth()));
00079 return result;
00080 }
00081
00082 static uint julianDayFromDate(int year, int month, int day)
00083 {
00084 if (year < 0)
00085 ++year;
00086
00087 if (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day >= 15)))) {
00088
00089
00090 return (1461 * (year + 4800 + (month - 14) / 12)) / 4
00091 + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12
00092 - (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4
00093 + day - 32075;
00094 } else if (year < 1582 || (year == 1582 && (month < 10 || (month == 10 && day <= 4)))) {
00095
00096
00097 int a = (14 - month) / 12;
00098 return (153 * (month + (12 * a) - 3) + 2) / 5
00099 + (1461 * (year + 4800 - a)) / 4
00100 + day - 32083;
00101 } else {
00102
00103 return 0;
00104 }
00105 }
00106
00107 static void getDateFromJulianDay(uint julianDay, int *year, int *month, int *day)
00108 {
00109 int y, m, d;
00110
00111 if (julianDay >= 2299161) {
00112
00113
00114 qulonglong ell, n, i, j;
00115 ell = qulonglong(julianDay) + 68569;
00116 n = (4 * ell) / 146097;
00117 ell = ell - (146097 * n + 3) / 4;
00118 i = (4000 * (ell + 1)) / 1461001;
00119 ell = ell - (1461 * i) / 4 + 31;
00120 j = (80 * ell) / 2447;
00121 d = ell - (2447 * j) / 80;
00122 ell = j / 11;
00123 m = j + 2 - (12 * ell);
00124 y = 100 * (n - 49) + i + ell;
00125 } else {
00126
00127
00128 julianDay += 32082;
00129 int dd = (4 * julianDay + 3) / 1461;
00130 int ee = julianDay - (1461 * dd) / 4;
00131 int mm = ((5 * ee) + 2) / 153;
00132 d = ee - (153 * mm + 2) / 5 + 1;
00133 m = mm + 3 - 12 * (mm / 10);
00134 y = dd - 4800 + (mm / 10);
00135 if (y <= 0)
00136 --y;
00137 }
00138 *year = y;
00139 *month = m;
00140 *day = d;
00141 }
00142
00143
00144 static const char monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00145
00146 #ifndef QT_NO_TEXTDATE
00147 static const char * const qt_shortMonthNames[] = {
00148 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00149 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
00150 #endif
00151 #ifndef QT_NO_DATESTRING
00152 static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0);
00153 #endif
00154
00155
00156
00157
00158
00230 QDate::QDate(int y, int m, int d)
00231 {
00232 if (uint(y) <= 99u)
00233 y += 1900;
00234 setDate(y, m, d);
00235 }
00236
00237
00254 bool QDate::isValid() const
00255 {
00256 return !isNull();
00257 }
00258
00259
00268 int QDate::year() const
00269 {
00270 int y, m, d;
00271 getDateFromJulianDay(jd, &y, &m, &d);
00272 return y;
00273 }
00274
00297 int QDate::month() const
00298 {
00299 int y, m, d;
00300 getDateFromJulianDay(jd, &y, &m, &d);
00301 return m;
00302 }
00303
00310 int QDate::day() const
00311 {
00312 int y, m, d;
00313 getDateFromJulianDay(jd, &y, &m, &d);
00314 return d;
00315 }
00316
00323 int QDate::dayOfWeek() const
00324 {
00325 return (jd % 7) + 1;
00326 }
00327
00334 int QDate::dayOfYear() const
00335 {
00336 return jd - julianDayFromDate(year(), 1, 1) + 1;
00337 }
00338
00345 int QDate::daysInMonth() const
00346 {
00347 int y, m, d;
00348 getDateFromJulianDay(jd, &y, &m, &d);
00349 if (m == 2 && isLeapYear(y))
00350 return 29;
00351 else
00352 return monthDays[m];
00353 }
00354
00361 int QDate::daysInYear() const
00362 {
00363 int y, m, d;
00364 getDateFromJulianDay(jd, &y, &m, &d);
00365 return isLeapYear(y) ? 366 : 365;
00366 }
00367
00401 int QDate::weekNumber(int *yearNumber) const
00402 {
00403 if (!isValid())
00404 return 0;
00405
00406 int year = QDate::year();
00407 int yday = dayOfYear() - 1;
00408 int wday = dayOfWeek();
00409 if (wday == 7)
00410 wday = 0;
00411 int w;
00412
00413 for (;;) {
00414 int len;
00415 int bot;
00416 int top;
00417
00418 len = isLeapYear(year) ? 366 : 365;
00419
00420
00421
00422
00423 bot = ((yday + 11 - wday) % 7) - 3;
00424
00425
00426
00427
00428 top = bot - (len % 7);
00429 if (top < -3)
00430 top += 7;
00431 top += len;
00432 if (yday >= top) {
00433 ++year;
00434 w = 1;
00435 break;
00436 }
00437 if (yday >= bot) {
00438 w = 1 + ((yday - bot) / 7);
00439 break;
00440 }
00441 --year;
00442 yday += isLeapYear(year) ? 366 : 365;
00443 }
00444 if (yearNumber != 0)
00445 *yearNumber = year;
00446 return w;
00447 }
00448
00449 #ifndef QT_NO_TEXTDATE
00450
00475 QString QDate::shortMonthName(int month)
00476 {
00477 if (month < 1 || month > 12) {
00478 qWarning("QDate::shortMonthName: Parameter out ouf range");
00479 month = 1;
00480 }
00481 return QLocale::system().monthName(month, QLocale::ShortFormat);
00482 }
00483
00509 QString QDate::longMonthName(int month)
00510 {
00511 if (month < 1 || month > 12) {
00512 qWarning("QDate::longMonthName: Parameter out ouf range");
00513 month = 1;
00514 }
00515 return QLocale::system().monthName(month, QLocale::LongFormat);
00516 }
00517
00538 QString QDate::shortDayName(int weekday)
00539 {
00540 if (weekday < 1 || weekday > 7) {
00541 qWarning("QDate::shortDayName: Parameter out of range");
00542 weekday = 1;
00543 }
00544 return QLocale::system().dayName(weekday, QLocale::ShortFormat);
00545 }
00546
00567 QString QDate::longDayName(int weekday)
00568 {
00569 if (weekday < 1 || weekday > 7) {
00570 qWarning("QDate::longDayName: Parameter out of range");
00571 weekday = 1;
00572 }
00573 return QLocale::system().dayName(weekday, QLocale::LongFormat);
00574 }
00575 #endif //QT_NO_TEXTDATE
00576
00577 #ifndef QT_NO_DATESTRING
00578
00619 QString QDate::toString(Qt::DateFormat f) const
00620 {
00621 if (!isValid())
00622 return QString();
00623 int y, m, d;
00624 getDateFromJulianDay(jd, &y, &m, &d);
00625 switch (f) {
00626 case Qt::SystemLocaleDate:
00627 return QLocale::system().toString(*this, QLocale::ShortFormat);
00628 case Qt::LocaleDate:
00629 return QLocale().toString(*this, QLocale::ShortFormat);
00630 default:
00631 #ifndef QT_NO_TEXTDATE
00632 case Qt::TextDate:
00633 {
00634 return QString::fromLatin1("%0 %1 %2 %3")
00635 .arg(shortDayName(dayOfWeek()))
00636 .arg(shortMonthName(m))
00637 .arg(d)
00638 .arg(y);
00639 }
00640 #endif
00641 case Qt::ISODate:
00642 {
00643 if (year() < 0 || year() > 9999)
00644 return QString();
00645 QString month(QString::number(m).rightJustified(2, QLatin1Char('0')));
00646 QString day(QString::number(d).rightJustified(2, QLatin1Char('0')));
00647 return QString::number(y) + QLatin1Char('-') + month + QLatin1Char('-') + day;
00648 }
00649 }
00650 }
00651
00702 QString QDate::toString(const QString& format) const
00703 {
00704 if (uint(year()) > 9999)
00705 return QString();
00706 return fmtDateTime(format, 0, this);
00707 }
00708 #endif //QT_NO_DATESTRING
00709
00721 bool QDate::setYMD(int y, int m, int d)
00722 {
00723 if (uint(y) <= 99)
00724 y += 1900;
00725 return setDate(y, m, d);
00726 }
00727
00740 bool QDate::setDate(int year, int month, int day)
00741 {
00742 if (!isValid(year, month, day)) {
00743 jd = 0;
00744 } else {
00745 jd = julianDayFromDate(year, month, day);
00746 }
00747 return jd != 0;
00748 }
00749
00757 QDate QDate::addDays(int ndays) const
00758 {
00759 QDate d;
00760 d.jd = jd + ndays;
00761 return d;
00762 }
00763
00771 QDate QDate::addMonths(int nmonths) const
00772 {
00773 int y, m, d;
00774 getDateFromJulianDay(jd, &y, &m, &d);
00775
00776 while (nmonths != 0) {
00777 if (nmonths < 0 && nmonths + 12 <= 0) {
00778 y--;
00779 nmonths+=12;
00780 } else if (nmonths < 0) {
00781 m+= nmonths;
00782 nmonths = 0;
00783 if (m <= 0) {
00784 --y;
00785 m += 12;
00786 }
00787 } else if (nmonths - 12 >= 0) {
00788 y++;
00789 nmonths -= 12;
00790 } else if (m == 12) {
00791 y++;
00792 m = 0;
00793 } else {
00794 m += nmonths;
00795 nmonths = 0;
00796 if (m > 12) {
00797 ++y;
00798 m -= 12;
00799 }
00800 }
00801 }
00802
00803 return fixedDate(y, m, d);
00804 }
00805
00813 QDate QDate::addYears(int nyears) const
00814 {
00815 int y, m, d;
00816 getDateFromJulianDay(jd, &y, &m, &d);
00817 y += nyears;
00818 return fixedDate(y, m, d);
00819 }
00820
00836 int QDate::daysTo(const QDate &d) const
00837 {
00838 return d.jd - jd;
00839 }
00840
00841
00891 QDate QDate::currentDate()
00892 {
00893 QDate d;
00894 #if defined(Q_OS_WIN)
00895 SYSTEMTIME st;
00896 memset(&st, 0, sizeof(SYSTEMTIME));
00897 GetLocalTime(&st);
00898 d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
00899 #else
00900
00901 time_t ltime;
00902 time(<ime);
00903 tm *t;
00904
00905 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
00906
00907 tm res;
00908 t = localtime_r(<ime, &res);
00909 #else
00910 t = localtime(<ime);
00911 #endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
00912
00913 d.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
00914 #endif
00915 return d;
00916 }
00917
00918 #ifndef QT_NO_DATESTRING
00919
00932 QDate QDate::fromString(const QString& s, Qt::DateFormat f)
00933 {
00934 if ((s.isEmpty()) || (f == Qt::LocalDate))
00935 return QDate();
00936
00937 switch (f) {
00938 case Qt::ISODate:
00939 {
00940 int year(s.mid(0, 4).toInt());
00941 int month(s.mid(5, 2).toInt());
00942 int day(s.mid(8, 2).toInt());
00943 if (year && month && day)
00944 return strictDate(year, month, day);
00945 }
00946 break;
00947 default:
00948 #ifndef QT_NO_TEXTDATE
00949 case Qt::TextDate:
00950 {
00951
00952
00953
00954
00955 int monthPos = s.indexOf(QLatin1Char(' ')) + 1;
00956 int dayPos = s.indexOf(QLatin1Char(' '), monthPos) + 1;
00957 int yearPos = s.indexOf(QLatin1Char(' '), dayPos) + 1;
00958
00959 QString monthName(s.mid(monthPos, dayPos - monthPos - 1));
00960 int month = -1;
00961
00962
00963 for (int i = 0; i < 12; i++) {
00964 if (monthName == QLatin1String(qt_shortMonthNames[i])) {
00965 month = i + 1;
00966 break;
00967 }
00968 }
00969
00970
00971 if (month == -1) {
00972 for (int i = 0; i < 12; i++) {
00973 if (monthName == shortMonthName(i + 1)) {
00974 month = i + 1;
00975 break;
00976 }
00977 }
00978 }
00979 if (month >= 1 && month <= 12) {
00980 int day = s.mid(dayPos, 2).trimmed().toInt();
00981 int year = s.mid(yearPos).toInt();
00982 return strictDate(year, month, day);
00983 }
00984 }
00985 #else
00986 break;
00987 #endif
00988 }
00989 return QDate();
00990 }
00991
01065 QDate QDate::fromString(const QString &string, const QString &format)
01066 {
01067 QDate date;
01068 #ifndef QT_BOOTSTRAPPED
01069 QDateTimeParser dt(QVariant::Date);
01070 if (dt.parseFormat(format))
01071 dt.fromString(string, &date, 0);
01072 #else
01073 Q_UNUSED(string);
01074 Q_UNUSED(format);
01075 #endif
01076 return date;
01077 }
01078 #endif // QT_NO_DATESTRING
01079
01100 bool QDate::isValid(int year, int month, int day)
01101 {
01102 if (year < FIRST_YEAR
01103 || (year == FIRST_YEAR && (month < FIRST_MONTH || month == FIRST_MONTH && day < FIRST_DAY))
01104 || year == 0)
01105 return false;
01106
01107
01108 if (year == 1582 && month == 10 && day > 4 && day < 15)
01109 return 0;
01110
01111 return (day > 0 && month > 0 && month <= 12) &&
01112 (day <= monthDays[month] || (day == 29 && month == 2 && isLeapYear(year)));
01113 }
01114
01122 bool QDate::isLeapYear(int y)
01123 {
01124 if (y < 1582) {
01125 return qAbs(y) % 4 == 0;
01126 } else {
01127 return y % 4 == 0 && y % 100 != 0 || y % 400 == 0;
01128 }
01129 }
01130
01138 uint QDate::gregorianToJulian(int y, int m, int d)
01139 {
01140 return julianDayFromDate(y, m, d);
01141 }
01142
01150 void QDate::julianToGregorian(uint jd, int &y, int &m, int &d)
01151 {
01152 getDateFromJulianDay(jd, &y, &m, &d);
01153 }
01154
01169
01170
01171
01172
01239 QTime::QTime(int h, int m, int s, int ms)
01240 {
01241 setHMS(h, m, s, ms);
01242 }
01243
01244
01262 bool QTime::isValid() const
01263 {
01264 return mds > NullTime && mds < MSECS_PER_DAY;
01265 }
01266
01267
01274 int QTime::hour() const
01275 {
01276 return ds() / MSECS_PER_HOUR;
01277 }
01278
01285 int QTime::minute() const
01286 {
01287 return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
01288 }
01289
01296 int QTime::second() const
01297 {
01298 return (ds() / 1000)%SECS_PER_MIN;
01299 }
01300
01307 int QTime::msec() const
01308 {
01309 return ds() % 1000;
01310 }
01311
01312 #ifndef QT_NO_DATESTRING
01313
01344 QString QTime::toString(Qt::DateFormat f) const
01345 {
01346 if (!isValid())
01347 return QString();
01348
01349 switch (f) {
01350 case Qt::SystemLocaleDate:
01351 return QLocale::system().toString(*this, QLocale::ShortFormat);
01352 case Qt::LocaleDate:
01353 return QLocale().toString(*this, QLocale::ShortFormat);
01354 default:
01355 case Qt::ISODate:
01356 case Qt::TextDate:
01357 return QString::fromLatin1("%1:%2:%3")
01358 .arg(hour(), 2, 10, QLatin1Char('0'))
01359 .arg(minute(), 2, 10, QLatin1Char('0'))
01360 .arg(second(), 2, 10, QLatin1Char('0'));
01361 }
01362 }
01363
01409 QString QTime::toString(const QString& format) const
01410 {
01411 return fmtDateTime(format, this, 0);
01412 }
01413 #endif //QT_NO_DATESTRING
01414
01425 bool QTime::setHMS(int h, int m, int s, int ms)
01426 {
01427 if (!isValid(h,m,s,ms)) {
01428 mds = NullTime;
01429 return false;
01430 }
01431 mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
01432 return true;
01433 }
01434
01455 QTime QTime::addSecs(int nsecs) const
01456 {
01457 return addMSecs(nsecs * 1000);
01458 }
01459
01471 int QTime::secsTo(const QTime &t) const
01472 {
01473 return (t.ds() - ds()) / 1000;
01474 }
01475
01486 QTime QTime::addMSecs(int ms) const
01487 {
01488 QTime t;
01489 if (ms < 0) {
01490
01491 int negdays = (MSECS_PER_DAY - ms) / MSECS_PER_DAY;
01492 t.mds = (ds() + ms + negdays * MSECS_PER_DAY) % MSECS_PER_DAY;
01493 } else {
01494 t.mds = (ds() + ms) % MSECS_PER_DAY;
01495 }
01496 return t;
01497 }
01498
01511 int QTime::msecsTo(const QTime &t) const
01512 {
01513 return t.ds() - ds();
01514 }
01515
01516
01564 QTime QTime::currentTime()
01565 {
01566 QTime ct;
01567
01568 #if defined(Q_OS_WIN)
01569 SYSTEMTIME st;
01570 memset(&st, 0, sizeof(SYSTEMTIME));
01571 GetLocalTime(&st);
01572 ct.mds = MSECS_PER_HOUR * st.wHour + MSECS_PER_MIN * st.wMinute + 1000 * st.wSecond
01573 + st.wMilliseconds;
01574 #elif defined(Q_OS_UNIX)
01575
01576 struct timeval tv;
01577 gettimeofday(&tv, 0);
01578 time_t ltime = tv.tv_sec;
01579 tm *t;
01580
01581 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
01582
01583 tm res;
01584 t = localtime_r(<ime, &res);
01585 #else
01586 t = localtime(<ime);
01587 #endif
01588
01589 ct.mds = MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + 1000 * t->tm_sec
01590 + tv.tv_usec / 1000;
01591 #else
01592 time_t ltime;
01593 ::time(<ime);
01594 tm *t;
01595 localtime(<ime);
01596 ct.mds = MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + 1000 * t->tm_sec;
01597 #endif
01598 return ct;
01599 }
01600
01601 #ifndef QT_NO_DATESTRING
01602
01610 QTime QTime::fromString(const QString& s, Qt::DateFormat f)
01611 {
01612 if (s.isEmpty() || f == Qt::LocalDate) {
01613 qWarning("QTime::fromString: Parameter out of range");
01614 QTime t;
01615 t.mds = NullTime;
01616 return t;
01617 }
01618
01619 const int hour(s.mid(0, 2).toInt());
01620 const int minute(s.mid(3, 2).toInt());
01621 const int second(s.mid(6, 2).toInt());
01622
01623 const QString msec_s(QLatin1String("0.") + s.mid(9, 4));
01624 const float msec(msec_s.toFloat());
01625 return QTime(hour, minute, second, qMin(qRound(msec * 1000.0), 999));
01626 }
01627
01687 QTime QTime::fromString(const QString &string, const QString &format)
01688 {
01689 QTime time;
01690 #ifndef QT_BOOTSTRAPPED
01691 QDateTimeParser dt(QVariant::Time);
01692 if (dt.parseFormat(format))
01693 dt.fromString(string, 0, &time);
01694 #else
01695 Q_UNUSED(string);
01696 Q_UNUSED(format);
01697 #endif
01698 return time;
01699 }
01700
01701 #endif // QT_NO_DATESTRING
01702
01703
01721 bool QTime::isValid(int h, int m, int s, int ms)
01722 {
01723 return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
01724 }
01725
01726
01740 void QTime::start()
01741 {
01742 *this = currentTime();
01743 }
01744
01765 int QTime::restart()
01766 {
01767 QTime t = currentTime();
01768 int n = msecsTo(t);
01769 if (n < 0)
01770 n += 86400*1000;
01771 *this = t;
01772 return n;
01773 }
01774
01793 int QTime::elapsed() const
01794 {
01795 int n = msecsTo(currentTime());
01796 if (n < 0)
01797 n += 86400 * 1000;
01798 return n;
01799 }
01800
01801
01802
01803
01804
01805
01860 QDateTime::QDateTime()
01861 {
01862 d = new QDateTimePrivate;
01863 }
01864
01865
01871 QDateTime::QDateTime(const QDate &date)
01872 {
01873 d = new QDateTimePrivate;
01874 d->date = date;
01875 d->time = QTime(0, 0, 0);
01876 }
01877
01885 QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
01886 {
01887 d = new QDateTimePrivate;
01888 d->date = date;
01889 d->time = date.isValid() && !time.isValid() ? QTime(0, 0, 0) : time;
01890 d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown;
01891 }
01892
01897 QDateTime::QDateTime(const QDateTime &other)
01898 {
01899 d = other.d;
01900 d->ref.ref();
01901 }
01902
01906 QDateTime::~QDateTime()
01907 {
01908 if (!d->ref.deref())
01909 delete d;
01910 }
01911
01917 QDateTime &QDateTime::operator=(const QDateTime &other)
01918 {
01919 qAtomicAssign(d, other.d);
01920 return *this;
01921 }
01922
01930 bool QDateTime::isNull() const
01931 {
01932 return d->date.isNull() && d->time.isNull();
01933 }
01934
01942 bool QDateTime::isValid() const
01943 {
01944 return d->date.isValid() && d->time.isValid();
01945 }
01946
01953 QDate QDateTime::date() const
01954 {
01955 return d->date;
01956 }
01957
01964 QTime QDateTime::time() const
01965 {
01966 return d->time;
01967 }
01968
01975 Qt::TimeSpec QDateTime::timeSpec() const
01976 {
01977 return d->spec == QDateTimePrivate::UTC ? Qt::UTC : Qt::LocalTime;
01978 }
01979
01987 void QDateTime::setDate(const QDate &date)
01988 {
01989 detach();
01990 d->date = date;
01991 if (date.isValid() && !d->time.isValid())
01992 d->time = QTime(0, 0, 0);
01993 }
01994
02001 void QDateTime::setTime(const QTime &time)
02002 {
02003 detach();
02004 d->time = time;
02005 }
02006
02013 void QDateTime::setTimeSpec(Qt::TimeSpec spec)
02014 {
02015 detach();
02016 d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown;
02017 }
02018
02019 static uint toTime_t(const QDate &utcDate, const QTime &utcTime)
02020 {
02021 int days = QDate(1970, 1, 1).daysTo(utcDate);
02022 int secs = QTime().secsTo(utcTime);
02023 if (days < 0 || (days == 0 && secs < 0))
02024 return uint(-1);
02025
02026 qlonglong retval = (qlonglong(days) * SECS_PER_DAY) + secs;
02027 if (retval >= Q_INT64_C(0xFFFFFFFF))
02028 return uint(-1);
02029 return uint(retval);
02030 }
02031
02042 uint QDateTime::toTime_t() const
02043 {
02044 QDate utcDate;
02045 QTime utcTime;
02046 d->getUTC(utcDate, utcTime);
02047
02048 return ::toTime_t(utcDate, utcTime);
02049 }
02050
02062 void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
02063 {
02064 detach();
02065
02066 QDateTimePrivate::Spec oldSpec = d->spec;
02067
02068 d->date = QDate(1970, 1, 1).addDays(secsSince1Jan1970UTC / SECS_PER_DAY);
02069 d->time = QTime().addSecs(secsSince1Jan1970UTC % SECS_PER_DAY);
02070 d->spec = QDateTimePrivate::UTC;
02071
02072 if (oldSpec != QDateTimePrivate::UTC)
02073 d->spec = d->getLocal(d->date, d->time);
02074 }
02075
02076 #ifndef QT_NO_DATESTRING
02077
02115 QString QDateTime::toString(Qt::DateFormat f) const
02116 {
02117 QString buf;
02118 if (!isValid())
02119 return buf;
02120
02121 if (f == Qt::ISODate) {
02122 buf = d->date.toString(Qt::ISODate);
02123 if (buf.isEmpty())
02124 return QString();
02125 buf += QLatin1Char('T');
02126 buf += d->time.toString(Qt::ISODate);
02127 }
02128 #ifndef QT_NO_TEXTDATE
02129 else if (f == Qt::TextDate) {
02130 #ifndef Q_WS_WIN
02131 buf = d->date.shortDayName(d->date.dayOfWeek());
02132 buf += QLatin1Char(' ');
02133 buf += d->date.shortMonthName(d->date.month());
02134 buf += QLatin1Char(' ');
02135 buf += QString::number(d->date.day());
02136 #else
02137 QString winstr;
02138 QT_WA({
02139 TCHAR out[255];
02140 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255);
02141 winstr = QString::fromUtf16((ushort*)out);
02142 } , {
02143 char out[255];
02144 GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ILDATE, (char*)&out, 255);
02145 winstr = QString::fromLocal8Bit(out);
02146 });
02147 switch (winstr.toInt()) {
02148 case 1:
02149 buf = d->date.shortDayName(d->date.dayOfWeek());
02150 buf += QLatin1Char(' ');
02151 buf += QString::number(d->date.day());
02152 buf += QLatin1String(". ");
02153 buf += d->date.shortMonthName(d->date.month());
02154 break;
02155 default:
02156 buf = d->date.shortDayName(d->date.dayOfWeek());
02157 buf += QLatin1Char(' ');
02158 buf += d->date.shortMonthName(d->date.month());
02159 buf += QLatin1Char(' ');
02160 buf += QString::number(d->date.day());
02161 }
02162 #endif
02163 buf += QLatin1Char(' ');
02164 buf += d->time.toString();
02165 buf += QLatin1Char(' ');
02166 buf += QString::number(d->date.year());
02167 }
02168 #endif
02169 else if (f == Qt::LocaleDate || f == Qt::SystemLocaleDate) {
02170 buf = d->date.toString(f);
02171 if (buf.isEmpty())
02172 return QString();
02173 buf += QLatin1Char(' ');
02174 buf += d->time.toString(f);
02175 }
02176 return buf;
02177 }
02178
02246 QString QDateTime::toString(const QString& format) const
02247 {
02248 return fmtDateTime(format, &d->time, &d->date);
02249 }
02250 #endif //QT_NO_DATESTRING
02251
02260 QDateTime QDateTime::addDays(int ndays) const
02261 {
02262 return QDateTime(d->date.addDays(ndays), d->time, timeSpec());
02263 }
02264
02273 QDateTime QDateTime::addMonths(int nmonths) const
02274 {
02275 return QDateTime(d->date.addMonths(nmonths), d->time, timeSpec());
02276 }
02277
02286 QDateTime QDateTime::addYears(int nyears) const
02287 {
02288 return QDateTime(d->date.addYears(nyears), d->time, timeSpec());
02289 }
02290
02291
02292 QDateTime QDateTimePrivate::addMSecs(const QDateTime &dt, qint64 msecs)
02293 {
02294 QDate utcDate;
02295 QTime utcTime;
02296 dt.d->getUTC(utcDate, utcTime);
02297
02298 uint dd = utcDate.jd;
02299 int tt = utcTime.ds();
02300 int sign = 1;
02301 if (msecs < 0) {
02302 msecs = -msecs;
02303 sign = -1;
02304 }
02305 if (msecs >= int(MSECS_PER_DAY)) {
02306 dd += sign * (msecs / MSECS_PER_DAY);
02307 msecs %= MSECS_PER_DAY;
02308 }
02309
02310 tt += sign * msecs;
02311 if (tt < 0) {
02312 tt = MSECS_PER_DAY - tt - 1;
02313 dd -= tt / MSECS_PER_DAY;
02314 tt = tt % MSECS_PER_DAY;
02315 tt = MSECS_PER_DAY - tt - 1;
02316 } else if (tt >= int(MSECS_PER_DAY)) {
02317 dd += tt / MSECS_PER_DAY;
02318 tt = tt % MSECS_PER_DAY;
02319 }
02320
02321 utcDate.jd = dd;
02322 utcTime.mds = tt;
02323 return QDateTime(utcDate, utcTime, Qt::UTC).toTimeSpec(dt.timeSpec());
02324 }
02325
02334 QDateTime QDateTime::addSecs(int nsecs) const
02335 {
02336 return d->addMSecs(*this, qint64(nsecs) * 1000);
02337 }
02338
02346 QDateTime QDateTime::addMSecs(qint64 msecs) const
02347 {
02348 return d->addMSecs(*this, msecs);
02349 }
02350
02359 int QDateTime::daysTo(const QDateTime &other) const
02360 {
02361 return d->date.daysTo(other.d->date);
02362 }
02363
02383 int QDateTime::secsTo(const QDateTime &other) const
02384 {
02385 QDate date1, date2;
02386 QTime time1, time2;
02387
02388 d->getUTC(date1, time1);
02389 other.d->getUTC(date2, time2);
02390
02391 return (date1.daysTo(date2) * SECS_PER_DAY) + time1.secsTo(time2);
02392 }
02393
02403 QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
02404 {
02405 if ((d->spec == QDateTimePrivate::UTC) == (spec == Qt::UTC))
02406 return *this;
02407
02408 QDateTime ret;
02409 if (spec == Qt::UTC) {
02410 d->getUTC(ret.d->date, ret.d->time);
02411 ret.d->spec = QDateTimePrivate::UTC;
02412 } else {
02413 ret.d->spec = d->getLocal(ret.d->date, ret.d->time);
02414 }
02415 return ret;
02416 }
02417
02425 bool QDateTime::operator==(const QDateTime &other) const
02426 {
02427 if (d->spec != other.d->spec) {
02428 if (d->spec == QDateTimePrivate::UTC || other.d->spec == QDateTimePrivate::UTC)
02429 return false;
02430 if (d->spec != QDateTimePrivate::LocalUnknown
02431 && other.d->spec != QDateTimePrivate::LocalUnknown)
02432 return false;
02433
02434 QDate date1, date2;
02435 QTime time1, time2;
02436 d->getUTC(date1, time1);
02437 other.d->getUTC(date2, time2);
02438 return time1 == time2 && date1 == date2;
02439 } else {
02440 return d->time == other.d->time && d->date == other.d->date;
02441 }
02442 }
02443
02461 bool QDateTime::operator<(const QDateTime &other) const
02462 {
02463 if (d->spec == other.d->spec) {
02464 if (d->date != other.d->date)
02465 return d->date < other.d->date;
02466 return d->time < other.d->time;
02467 } else {
02468 QDate date1, date2;
02469 QTime time1, time2;
02470 d->getUTC(date1, time1);
02471 other.d->getUTC(date2, time2);
02472 if (date1 != date2)
02473 return date1 < date2;
02474 return time1 < time2;
02475 }
02476 }
02477
02506 QDateTime QDateTime::currentDateTime()
02507 {
02508 #if defined(Q_OS_WIN)
02509 QDate d;
02510 QTime t;
02511 SYSTEMTIME st;
02512 memset(&st, 0, sizeof(SYSTEMTIME));
02513 GetLocalTime(&st);
02514 d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
02515 t.mds = MSECS_PER_HOUR * st.wHour + MSECS_PER_MIN * st.wMinute + 1000 * st.wSecond
02516 + st.wMilliseconds;
02517 return QDateTime(d, t);
02518 #else
02519 QDateTime dt;
02520 QTime t;
02521 dt.setDate(QDate::currentDate());
02522 t = QTime::currentTime();
02523 if (t.ds() < MSECS_PER_MIN)
02524 dt.setDate(QDate::currentDate());
02525 dt.setTime(t);
02526 return dt;
02527 #endif
02528 }
02529
02540 QDateTime QDateTime::fromTime_t(uint seconds)
02541 {
02542 QDateTime d;
02543 d.setTime_t(seconds);
02544 return d;
02545 }
02546
02547 #ifndef QT_NO_DATESTRING
02548
02560 QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
02561 {
02562 if (s.isEmpty() || f == Qt::LocalDate) {
02563 qWarning("QDateTime::fromString: Parameter out of range");
02564 return QDateTime();
02565 }
02566 if (f == Qt::ISODate) {
02567 QString tmp = s;
02568 Qt::TimeSpec ts = Qt::LocalTime;
02569
02570
02571 if (tmp.endsWith(QLatin1Char('Z'))) {
02572 ts = Qt::UTC;
02573 tmp.chop(1);
02574 }
02575 return QDateTime(QDate::fromString(tmp.mid(0, 10), Qt::ISODate),
02576 QTime::fromString(tmp.mid(11), Qt::ISODate), ts);
02577 }
02578 #if !defined(QT_NO_REGEXP) && !defined(QT_NO_TEXTDATE)
02579 else if (f == Qt::TextDate) {
02580 QString monthName(s.mid(4, 3));
02581 int month = -1;
02582
02583 for (int i = 0; i < 12; ++i) {
02584 if (monthName == QLatin1String(qt_shortMonthNames[i])) {
02585 month = i + 1;
02586 break;
02587 }
02588 }
02589
02590 if (month == -1) {
02591 for (int i = 1; i <= 12; ++i) {
02592 if (monthName == QDate::shortMonthName(i)) {
02593 month = i;
02594 break;
02595 }
02596 }
02597 }
02598 if (month < 1 || month > 12) {
02599 qWarning("QDateTime::fromString: Parameter out of range");
02600 return QDateTime();
02601 }
02602 int day = s.mid(8, 2).simplified().toInt();
02603 int yearPos = s.lastIndexOf(QLatin1Char(' ')) + 1;
02604 int year = s.mid(yearPos).toInt();
02605 QDate date = strictDate(year, month, day);
02606 QTime time;
02607 int hour, minute, second;
02608 int pivot = s.indexOf(QRegExp(QString::fromLatin1("[0-9][0-9]:[0-9][0-9]:[0-9][0-9]")));
02609 if (pivot != -1) {
02610 hour = s.mid(pivot, 2).toInt();
02611 minute = s.mid(pivot + 3, 2).toInt();
02612 second = s.mid(pivot + 6, 2).toInt();
02613 time.setHMS(hour, minute, second);
02614 }
02615 return QDateTime(date, time);
02616 }
02617 #endif //QT_NO_REGEXP
02618 return QDateTime();
02619 }
02620
02727 QDateTime QDateTime::fromString(const QString &string, const QString &format)
02728 {
02729 #ifndef QT_BOOTSTRAPPED
02730 QTime time;
02731 QDate date;
02732
02733 QDateTimeParser dt(QVariant::DateTime);
02734 if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
02735 return QDateTime(date, time);
02736 #else
02737 Q_UNUSED(string);
02738 Q_UNUSED(format);
02739 #endif
02740 return QDateTime(QDate(), QTime(-1, -1, -1));
02741 }
02742
02743 #endif // QT_NO_DATESTRING
02744
02764 void QDateTime::detach()
02765 {
02766 qAtomicDetach(d);
02767 }
02768
02769
02770
02771
02772
02773 #ifndef QT_NO_DATASTREAM
02774
02782 QDataStream &operator<<(QDataStream &out, const QDate &date)
02783 {
02784 return out << (quint32)(date.jd);
02785 }
02786
02795 QDataStream &operator>>(QDataStream &in, QDate &date)
02796 {
02797 quint32 jd;
02798 in >> jd;
02799 date.jd = jd;
02800 return in;
02801 }
02802
02811 QDataStream &operator<<(QDataStream &out, const QTime &time)
02812 {
02813 return out << quint32(time.mds);
02814 }
02815
02824 QDataStream &operator>>(QDataStream &in, QTime &time)
02825 {
02826 quint32 ds;
02827 in >> ds;
02828 time.mds = int(ds);
02829 return in;
02830 }
02831
02839 QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
02840 {
02841 out << dateTime.d->date << dateTime.d->time;
02842 if (out.version() >= 7)
02843 out << (qint8)dateTime.d->spec;
02844 return out;
02845 }
02846
02855 QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
02856 {
02857 dateTime.detach();
02858
02859 qint8 ts = (qint8)QDateTimePrivate::LocalUnknown;
02860 in >> dateTime.d->date >> dateTime.d->time;
02861 if (in.version() >= 7)
02862 in >> ts;
02863 dateTime.d->spec = (QDateTimePrivate::Spec)ts;
02864 return in;
02865 }
02866 #endif // QT_NO_DATASTREAM
02867
02868
02938
02939 static bool hasUnquotedAP(const QString &f)
02940 {
02941 const QLatin1Char quote('\'');
02942 bool inquote = false;
02943 for (int i=0; i < f.size(); ++i) {
02944 if (f.at(i) == quote) {
02945 inquote = !inquote;
02946 } else if (!inquote && f.at(i).toUpper() == QLatin1Char('A')) {
02947 return true;
02948 }
02949 }
02950 return false;
02951 }
02952
02953 #ifndef QT_NO_DATESTRING
02954
02955
02956
02957
02958
02959 static QString getFmtString(const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = false)
02960 {
02961 if (f.isEmpty())
02962 return QString();
02963
02964 QString buf = f;
02965 int removed = 0;
02966
02967 if (dt) {
02968 if (f.startsWith(QLatin1String("hh")) || f.startsWith(QLatin1String("HH"))) {
02969 const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
02970 if (hour12 && dt->hour() > 12)
02971 buf = QString::number(dt->hour() - 12).rightJustified(2, QLatin1Char('0'), true);
02972 else if (hour12 && dt->hour() == 0)
02973 buf = QLatin1String("12");
02974 else
02975 buf = QString::number(dt->hour()).rightJustified(2, QLatin1Char('0'), true);
02976 removed = 2;
02977 } else if (f.at(0) == QLatin1Char('h') || f.at(0) == QLatin1Char('H')) {
02978 const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
02979 if (hour12 && dt->hour() > 12)
02980 buf = QString::number(dt->hour() - 12);
02981 else if (hour12 && dt->hour() == 0)
02982 buf = QLatin1String("12");
02983 else
02984 buf = QString::number(dt->hour());
02985 removed = 1;
02986 } else if (f.startsWith(QLatin1String("mm"))) {
02987 buf = QString::number(dt->minute()).rightJustified(2, QLatin1Char('0'), true);
02988 removed = 2;
02989 } else if (f.at(0) == (QLatin1Char('m'))) {
02990 buf = QString::number(dt->minute());
02991 removed = 1;
02992 } else if (f.startsWith(QLatin1String("ss"))) {
02993 buf = QString::number(dt->second()).rightJustified(2, QLatin1Char('0'), true);
02994 removed = 2;
02995 } else if (f.at(0) == QLatin1Char('s')) {
02996 buf = QString::number(dt->second());
02997 } else if (f.startsWith(QLatin1String("zzz"))) {
02998 buf = QString::number(dt->msec()).rightJustified(3, QLatin1Char('0'), true);
02999 removed = 3;
03000 } else if (f.at(0) == QLatin1Char('z')) {
03001 buf = QString::number(dt->msec());
03002 removed = 1;
03003 } else if (f.at(0).toUpper() == QLatin1Char('A')) {
03004 const bool upper = f.at(0) == QLatin1Char('A');
03005 buf = dt->hour() < 12 ? QLatin1String("am") : QLatin1String("pm");
03006 if (upper)
03007 buf = buf.toUpper();
03008 if (f.size() > 1 && f.at(1).toUpper() == QLatin1Char('P') &&
03009 f.at(0).isUpper() == f.at(1).isUpper()) {
03010 removed = 2;
03011 } else {
03012 removed = 1;
03013 }
03014 }
03015 }
03016
03017 if (dd) {
03018 if (f.startsWith(QLatin1String("dddd"))) {
03019 buf = dd->longDayName(dd->dayOfWeek());
03020 removed = 4;
03021 } else if (f.startsWith(QLatin1String("ddd"))) {
03022 buf = dd->shortDayName(dd->dayOfWeek());
03023 removed = 3;
03024 } else if (f.startsWith(QLatin1String("dd"))) {
03025 buf = QString::number(dd->day()).rightJustified(2, QLatin1Char('0'), true);
03026 removed = 2;
03027 } else if (f.at(0) == QLatin1Char('d')) {
03028 buf = QString::number(dd->day());
03029 removed = 1;
03030 } else if (f.startsWith(QLatin1String("MMMM"))) {
03031 buf = dd->longMonthName(dd->month());
03032 removed = 4;
03033 } else if (f.startsWith(QLatin1String("MMM"))) {
03034 buf = dd->shortMonthName(dd->month());
03035 removed = 3;
03036 } else if (f.startsWith(QLatin1String("MM"))) {
03037 buf = QString::number(dd->month()).rightJustified(2, QLatin1Char('0'), true);
03038 removed = 2;
03039 } else if (f.at(0) == QLatin1Char('M')) {
03040 buf = QString::number(dd->month());
03041 removed = 1;
03042 } else if (f.startsWith(QLatin1String("yyyy"))) {
03043 buf = QString::number(dd->year());
03044 removed = 4;
03045 } else if (f.startsWith(QLatin1String("yy"))) {
03046 buf = QString::number(dd->year()).right(2);
03047 removed = 2;
03048 }
03049 }
03050 if (removed == 0 || removed >= f.size()) {
03051 return buf;
03052 }
03053
03054 return buf + getFmtString(f.mid(removed), dt, dd, am_pm);
03055 }
03056
03057
03058 static QString fmtDateTime(const QString& f, const QTime* dt, const QDate* dd)
03059 {
03060 const QLatin1Char quote('\'');
03061 if (f.isEmpty())
03062 return QString();
03063 if (dt && !dt->isValid())
03064 return QString();
03065 if (dd && !dd->isValid())
03066 return QString();
03067
03068 const bool ap = hasUnquotedAP(f);
03069
03070 QString buf;
03071 QString frm;
03072 QChar status = QLatin1Char('0');
03073
03074 for (int i = 0; i < (int)f.length(); ++i) {
03075 if (f.at(i) == quote) {
03076 if (status == quote) {
03077 status = QLatin1Char('0');
03078 } else {
03079 if (!frm.isEmpty()) {
03080 buf += getFmtString(frm, dt, dd, ap);
03081 frm.clear();
03082 }
03083 status = quote;
03084 }
03085 } else if (status == quote) {
03086 buf += f.at(i);
03087 } else if (f.at(i) == status) {
03088 if ((ap) && ((f.at(i) == QLatin1Char('P')) || (f.at(i) == QLatin1Char('p'))))
03089 status = QLatin1Char('0');
03090 frm += f.at(i);
03091 } else {
03092 buf += getFmtString(frm, dt, dd, ap);
03093 frm.clear();
03094 if ((f.at(i) == QLatin1Char('h')) || (f.at(i) == QLatin1Char('m'))
03095 || (f.at(i) == QLatin1Char('H'))
03096 || (f.at(i) == QLatin1Char('s')) || (f.at(i) == QLatin1Char('z'))) {
03097 status = f.at(i);
03098 frm += f.at(i);
03099 } else if ((f.at(i) == QLatin1Char('d')) || (f.at(i) == QLatin1Char('M')) || (f.at(i) == QLatin1Char('y'))) {
03100 status = f.at(i);
03101 frm += f.at(i);
03102 } else if ((ap) && (f.at(i) == QLatin1Char('A'))) {
03103 status = QLatin1Char('P');
03104 frm += f.at(i);
03105 } else if((ap) && (f.at(i) == QLatin1Char('a'))) {
03106 status = QLatin1Char('p');
03107 frm += f.at(i);
03108 } else {
03109 buf += f.at(i);
03110 status = QLatin1Char('0');
03111 }
03112 }
03113 }
03114
03115 buf += getFmtString(frm, dt, dd, ap);
03116
03117 return buf;
03118 }
03119 #endif // QT_NO_DATESTRING
03120
03121 #ifdef Q_OS_WIN
03122 static const int LowerYear = 1980;
03123 #else
03124 static const int LowerYear = 1970;
03125 #endif
03126
03127 static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time)
03128 {
03129 QDate lowerLimit(LowerYear, 1, 2);
03130 QDate upperLimit(2037, 12, 30);
03131
03132 QDate fakeDate = date;
03133
03134 if (fakeDate < lowerLimit) {
03135 fakeDate = lowerLimit;
03136 } else if (fakeDate > upperLimit) {
03137 fakeDate = upperLimit;
03138 }
03139
03140 time_t secsSince1Jan1970UTC = toTime_t(fakeDate, time);
03141 tm *brokenDown = 0;
03142
03143 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
03144
03145 tm res;
03146 brokenDown = localtime_r(&secsSince1Jan1970UTC, &res);
03147 #elif defined(_MSC_VER) && _MSC_VER >= 1400
03148 tm res;
03149 if (!_localtime64_s(&res, &secsSince1Jan1970UTC))
03150 brokenDown = &res;
03151 #else
03152 brokenDown = localtime(&secsSince1Jan1970UTC);
03153 #endif
03154 if (!brokenDown) {
03155 date = QDate(1970, 1, 1);
03156 time = QTime();
03157 return QDateTimePrivate::LocalUnknown;
03158 } else {
03159 int deltaDays = fakeDate.daysTo(date);
03160 date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
03161 time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
03162 date = date.addDays(deltaDays);
03163 if (brokenDown->tm_isdst > 0)
03164 return QDateTimePrivate::LocalDST;
03165 else if (brokenDown->tm_isdst < 0)
03166 return QDateTimePrivate::LocalUnknown;
03167 else
03168 return QDateTimePrivate::LocalStandard;
03169 }
03170 }
03171
03172 static void localToUtc(QDate &date, QTime &time, int isdst)
03173 {
03174 if (!date.isValid())
03175 return;
03176
03177 QDate lowerLimit(LowerYear, 1, 2);
03178 QDate upperLimit(2037, 12, 30);
03179
03180 QDate fakeDate = date;
03181
03182 if (fakeDate < lowerLimit) {
03183 fakeDate = lowerLimit;
03184 isdst = false;
03185 } else if (fakeDate > upperLimit) {
03186 fakeDate = upperLimit;
03187 isdst = false;
03188 }
03189
03190 tm localTM;
03191 localTM.tm_sec = time.second();
03192 localTM.tm_min = time.minute();
03193 localTM.tm_hour = time.hour();
03194 localTM.tm_mday = fakeDate.day();
03195 localTM.tm_mon = fakeDate.month() - 1;
03196 localTM.tm_year = fakeDate.year() - 1900;
03197 localTM.tm_isdst = (int)isdst;
03198
03199 time_t secsSince1Jan1970UTC = mktime(&localTM);
03200 tm *brokenDown = 0;
03201
03202 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
03203
03204 tm res;
03205 brokenDown = gmtime_r(&secsSince1Jan1970UTC, &res);
03206 #elif defined(_MSC_VER) && _MSC_VER >= 1400
03207 tm res;
03208 if (!_gmtime64_s(&res, &secsSince1Jan1970UTC))
03209 brokenDown = &res;
03210 #else
03211 brokenDown = gmtime(&secsSince1Jan1970UTC);
03212 #endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
03213 if (!brokenDown) {
03214 date = QDate(1970, 1, 1);
03215 time = QTime();
03216 } else {
03217 int deltaDays = fakeDate.daysTo(date);
03218 date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
03219 time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
03220 date = date.addDays(deltaDays);
03221 }
03222 }
03223
03224 QDateTimePrivate::Spec QDateTimePrivate::getLocal(QDate &outDate, QTime &outTime) const
03225 {
03226 outDate = date;
03227 outTime = time;
03228 if (spec == QDateTimePrivate::UTC)
03229 return utcToLocal(outDate, outTime);
03230 return spec;
03231 }
03232
03233 void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const
03234 {
03235 outDate = date;
03236 outTime = time;
03237 if (spec != QDateTimePrivate::UTC)
03238 localToUtc(outDate, outTime, (int)spec);
03239 }
03240
03241 #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
03242 QDebug operator<<(QDebug dbg, const QDate &date)
03243 {
03244 dbg.nospace() << "QDate(" << date.toString() << ")";
03245 return dbg.space();
03246 }
03247
03248 QDebug operator<<(QDebug dbg, const QTime &time)
03249 {
03250 dbg.nospace() << "QTime(" << time.toString() << ")";
03251 return dbg.space();
03252 }
03253
03254 QDebug operator<<(QDebug dbg, const QDateTime &date)
03255 {
03256 dbg.nospace() << "QDateTime(" << date.toString() << ")";
03257 return dbg.space();
03258 }
03259 #endif
03260
03261 #ifndef QT_BOOTSTRAPPED
03262 bool QDateTimeParser::isSpecial(const QChar &c) const
03263 {
03264 switch (c.cell()) {
03265 case 'd': case 'M': case 'y':
03266 return (typ == QVariant::Date || typ == QVariant::DateTime);
03267 case 'H': case 'h': case 'm': case 's': case 'z': case 'a': case 'p': case 'A':
03268 return (typ == QVariant::Time || typ == QVariant::DateTime);
03269 case '\'': return true;
03270 default: return false;
03271 }
03272 }
03273
03274
03284 int QDateTimeParser::getDigit(const QVariant &t, Section s) const
03285 {
03286 switch (s) {
03287 case Hour24Section: case Hour12Section: return t.toTime().hour();
03288 case MinuteSection: return t.toTime().minute();
03289 case SecondSection: return t.toTime().second();
03290 case MSecSection: return t.toTime().msec();
03291 case YearSection: return t.toDate().year();
03292 case MonthSection: return t.toDate().month();
03293 case DaySection: return t.toDate().day();
03294 case AmPmSection: return t.toTime().hour() > 11 ? 1 : 0;
03295
03296 default: break;
03297 }
03298 qFatal("%s passed to getDigit. This should never happen", sectionName(s).toLatin1().constData());
03299 return -1;
03300 }
03301
03314 void QDateTimeParser::setDigit(QVariant &v, Section section, int newVal) const
03315 {
03316 int year, month, day, hour, minute, second, msec;
03317 const QDateTime &dt = v.toDateTime();
03318 year = dt.date().year();
03319 month = dt.date().month();
03320 day = dt.date().day();
03321 hour = dt.time().hour();
03322 minute = dt.time().minute();
03323 second = dt.time().second();
03324 msec = dt.time().msec();
03325
03326 switch (section) {
03327 case Hour24Section: case Hour12Section: hour = newVal; break;
03328 case MinuteSection: minute = newVal; break;
03329 case SecondSection: second = newVal; break;
03330 case MSecSection: msec = newVal; break;
03331 case YearSection: year = newVal; break;
03332 case MonthSection: month = newVal; break;
03333 case DaySection: day = newVal; break;
03334 case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
03335 default:
03336 qFatal("%s passed to setDigit. This should never happen", sectionName(section).toLatin1().constData());
03337 break;
03338 }
03339
03340 if (section != DaySection) {
03341 day = qMax<int>(cachedDay, day);
03342 }
03343
03344 v = QVariant(QDateTime(fixedDate(year, month, day), QTime(hour, minute, second, msec)));
03345 }
03346
03347
03348
03355 int QDateTimeParser::absoluteMax(int s) const
03356 {
03357 const SectionNode sn = sectionNode(s);
03358 switch (sn.type) {
03359 case Hour24Section:
03360 case Hour12Section: return 23;
03361 case MinuteSection:
03362 case SecondSection: return 59;
03363 case MSecSection: return 999;
03364 case YearSection: return sn.count == 2 ? 99 : 9999;
03365 case MonthSection: return 12;
03366 case DaySection: return 31;
03367 case AmPmSection: return 1;
03368 default: break;
03369 }
03370 qFatal("%s passed to max. This should never happen", sectionName(s).toLatin1().constData());
03371 return -1;
03372
03373 }
03374
03381 int QDateTimeParser::absoluteMin(int s) const
03382 {
03383 const SectionNode sn = sectionNode(s);
03384 switch (sn.type){
03385 case Hour24Section:
03386 case Hour12Section:
03387 case MinuteSection:
03388 case SecondSection:
03389 case MSecSection:
03390 case YearSection: return 0;
03391 case MonthSection:
03392 case DaySection: return 1;
03393 case AmPmSection: return 0;
03394 default: break;
03395 }
03396 qFatal("%s passed to min. This should never happen", sectionName(s).toLatin1().constData());
03397 return -1;
03398 }
03399
03406 QDateTimeParser::SectionNode QDateTimeParser::sectionNode(int sectionIndex) const
03407 {
03408 if (sectionIndex == FirstSectionIndex) {
03409 return first;
03410 } else if (sectionIndex == LastSectionIndex) {
03411 return last;
03412 } else if (sectionIndex == NoSectionIndex) {
03413 return none;
03414 }
03415 Q_ASSERT(sectionIndex >= 0 && sectionIndex < sectionNodes.size());
03416 return sectionNodes.at(sectionIndex);
03417 }
03418
03419 QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const
03420 {
03421 return sectionNode(sectionIndex).type;
03422 }
03423
03424
03431 int QDateTimeParser::sectionPos(int sectionIndex) const
03432 {
03433 return sectionPos(sectionNode(sectionIndex));
03434 }
03435
03436 int QDateTimeParser::sectionPos(const SectionNode &sn) const
03437 {
03438 switch (sn.type) {
03439 case FirstSection: return 0;
03440 case LastSection: return displayText().size() - 1;
03441 default: break;
03442 }
03443 if (sn.pos == -1)
03444 QDTPDEBUG << sectionName(sn.type) << sectionNodes.indexOf(sn);
03445 Q_ASSERT(sn.pos != -1);
03446 return sn.pos;
03447 }
03448
03449
03456 static QString unquote(const QString &str)
03457 {
03458 const QLatin1Char quote('\'');
03459 const QLatin1Char slash('\\');
03460 const QLatin1Char zero('0');
03461 QString ret;
03462 QChar status = zero;
03463 for (int i=0; i<str.size(); ++i) {
03464 if (str.at(i) == quote) {
03465 if (status != quote) {
03466 status = quote;
03467 } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
03468 ret[ret.size() - 1] = quote;
03469 } else {
03470 status = zero;
03471 }
03472 } else {
03473 ret += str.at(i);
03474 }
03475 }
03476 return ret;
03477 }
03486 static int countRepeat(const QString &str, int index)
03487 {
03488 Q_ASSERT(index >= 0 && index < str.size());
03489 int count = 1;
03490 const QChar ch = str.at(index);
03491 while (index + count < str.size() && str.at(index + count) == ch)
03492 ++count;
03493 return count;
03494 }
03495
03496 bool QDateTimeParser::parseFormat(const QString &newFormat)
03497 {
03498 const QLatin1Char quote('\'');
03499 const QLatin1Char slash('\\');
03500 const QLatin1Char zero('0');
03501 if (newFormat == displayFormat && !newFormat.isEmpty()) {
03502 return true;
03503 }
03504
03505 QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData());
03506
03507 const bool ap = hasUnquotedAP(newFormat);
03508 QList<SectionNode> newSectionNodes;
03509 Sections newDisplay = 0;
03510 QStringList newSeparators;
03511 int i, index = 0;
03512 int add = 0;
03513 QChar status = zero;
03514 for (i = 0; i<newFormat.size(); ++i) {
03515 if (newFormat.at(i) == quote) {
03516 ++add;
03517 if (status != quote) {
03518 status = quote;
03519 } else if (newFormat.at(i - 1) != slash) {
03520 status = zero;
03521 }
03522 } else if (i < newFormat.size() && status != quote) {
03523 const int repeat = qMin(4, countRepeat(newFormat, i));
03524 if (isSpecial(newFormat.at(i))) {
03525 const char sect = newFormat.at(i).toLatin1();
03526 switch (sect) {
03527 case 'H':
03528 case 'h': {
03529 const Section hour = (ap && sect == 'h') ? Hour12Section : Hour24Section;
03530 const SectionNode sn = { hour, i - add, qMin(2, repeat) };
03531 newSectionNodes << sn;
03532 newSeparators << unquote(newFormat.mid(index, i - index));
03533 i += sn.count - 1;
03534 index = i + 1;
03535 newDisplay |= hour;
03536 break; }
03537 case 'm': {
03538 const SectionNode sn = { MinuteSection, i - add, qMin(2, repeat) };
03539 newSectionNodes << sn;
03540 newSeparators << unquote(newFormat.mid(index, i - index));
03541 i += sn.count - 1;
03542 index = i + 1;
03543 newDisplay |= MinuteSection;
03544 break; }
03545 case 's': {
03546 const SectionNode sn = { SecondSection, i - add, qMin(2, repeat) };
03547 newSectionNodes << sn;
03548 newSeparators << unquote(newFormat.mid(index, i - index));
03549 i += qMin(2, repeat) - 1;
03550 index = i + 1;
03551 newDisplay |= SecondSection;
03552 break; }
03553
03554 case 'z': {
03555 const SectionNode sn = { MSecSection, i - add, (repeat < 3 ? 1 : 3) };
03556 newSectionNodes << sn;
03557 newSeparators << unquote(newFormat.mid(index, i - index));
03558 i += sn.count - 1;
03559 index = i + 1;
03560 newDisplay |= MSecSection;
03561 break; }
03562 case 'A':
03563 case 'a': {
03564 const bool cap = newFormat.at(i) == QLatin1Char('A');
03565 const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0) };
03566 newSectionNodes << sn;
03567 newSeparators << unquote(newFormat.mid(index, i - index));
03568 newDisplay |= AmPmSection;
03569 if (i + 1 < newFormat.size()
03570 && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
03571 ++i;
03572 }
03573 index = i + 1;
03574 break; }
03575 case 'y':
03576 if (repeat >= 2) {
03577 const bool four = repeat >= 4;
03578 const SectionNode sn = { YearSection, i - add, four ? 4 : 2 };
03579 newSectionNodes << sn;
03580 newSeparators << unquote(newFormat.mid(index, i - index));
03581 i += sn.count - 1;
03582 index = i + 1;
03583 newDisplay |= YearSection;
03584 }
03585 break;
03586 case 'M': {
03587 const SectionNode sn = { MonthSection, i - add, repeat };
03588 newSectionNodes << sn;
03589 newSeparators << unquote(newFormat.mid(index, i - index));
03590 i += sn.count - 1;
03591 index = i + 1;
03592 newDisplay |= MonthSection;
03593 break; }
03594 case 'd': {
03595 const SectionNode sn = { DaySection, i - add, repeat };
03596 newSectionNodes << sn;
03597 newSeparators << unquote(newFormat.mid(index, i - index));
03598 i += sn.count - 1;
03599 index = i + 1;
03600 newDisplay |= DaySection;
03601 break; }
03602
03603 default:
03604 break;
03605 }
03606 }
03607 }
03608 }
03609 if (newSectionNodes.isEmpty() && !allowEmpty) {
03610 return false;
03611 }
03612
03613 newSeparators << (index < newFormat.size() ? unquote(newFormat.mid(index)) : QString());
03614
03615 displayFormat = newFormat;
03616 separators = newSeparators;
03617 sectionNodes = newSectionNodes;
03618 display = newDisplay;
03619 last.pos = -1;
03620
03621
03622
03623
03624
03625 QDTPDEBUG << newFormat << displayFormat;
03626 QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData());
03627
03628 return true;
03629 }
03630
03637 int QDateTimeParser::sectionSize(int sectionIndex) const
03638 {
03639 if (sectionIndex < 0)
03640 return 0;
03641 Q_ASSERT(sectionIndex < sectionNodes.size());
03642 if (sectionIndex == sectionNodes.size() - 1) {
03643 return displayText().size() - sectionPos(sectionIndex) - separators.last().size();
03644 } else {
03645 return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex)
03646 - separators.at(sectionIndex + 1).size();
03647 }
03648 }
03649
03650
03651 int QDateTimeParser::sectionMaxSize(Section s, int count) const
03652 {
03653 #ifndef QT_NO_TEXTDATE
03654 int mcount = 12;
03655 QString(*nameFunction)(int) = 0;
03656 #endif
03657
03658 switch (s) {
03659 case FirstSection:
03660 case NoSection:
03661 case LastSection: return 0;
03662
03663 case AmPmSection: {
03664 const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(),
03665 getAmPmText(PmText, LowerCase).size());
03666 const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(),
03667 getAmPmText(PmText, UpperCase).size());
03668 return qMin(4, qMin(lowerMax, upperMax));
03669 }
03670
03671 case Hour24Section:
03672 case Hour12Section:
03673 case MinuteSection:
03674 case SecondSection: return 2;
03675 case DaySection:
03676 #ifdef QT_NO_TEXTDATE
03677 return 2;
03678 #else
03679 if (count <= 2)
03680 return 2;
03681 nameFunction = (count == 4 ? &QDate::longDayName : &QDate::shortDayName);
03682 mcount = 7;
03683
03684 #endif
03685 case MonthSection:
03686 if (count <= 2)
03687 return 2;
03688
03689 #ifdef QT_NO_TEXTDATE
03690 return 2;
03691 #else
03692 if (s == MonthSection) {
03693 nameFunction = count == 4
03694 ? &QDate::longMonthName : &QDate::shortMonthName;
03695 }
03696 Q_ASSERT(nameFunction);
03697 {
03698 int ret = 0;
03699 for (int i=1; i<=mcount; ++i) {
03700 ret = qMax(nameFunction(i).size(), ret);
03701 }
03702 return ret;
03703 }
03704 #endif
03705 case MSecSection: return 3;
03706 case YearSection: return count;
03707
03708 case Internal:
03709 case TimeSectionMask:
03710 case DateSectionMask: qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s", sectionName(s).toLatin1().constData());
03711 }
03712 return -1;
03713 }
03714
03715
03716 int QDateTimeParser::sectionMaxSize(int index) const
03717 {
03718 const SectionNode sn = sectionNode(index);
03719 return sectionMaxSize(sn.type, sn.count);
03720 }
03721
03730 QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const
03731 {
03732 const SectionNode &sn = sectionNode(sectionIndex);
03733 switch (sn.type) {
03734 case NoSectionIndex:
03735 case FirstSectionIndex:
03736 case LastSectionIndex:
03737 return QString();
03738 default: break;
03739 }
03740
03741 return text.mid(index, sectionSize(sectionIndex));
03742 }
03743
03744 #ifndef QT_NO_TEXTDATE
03745
03753 int QDateTimeParser::parseSection(int sectionIndex, QString &text, int index,
03754 State &state, int *usedptr) const
03755 {
03756 state = Invalid;
03757 int num = 0;
03758 const SectionNode sn = sectionNode(sectionIndex);
03759 Q_ASSERT(sn.type != NoSection && sn.type != FirstSection && sn.type != LastSection);
03760
03761 QString sectiontext = text.mid(index, sectionMaxSize(sectionIndex));
03762
03763 QDTPDEBUG << "sectionValue for" << sectionName(sn.type)
03764 << "with text" << text << "and st" << sectiontext
03765 << text.mid(index, sectionMaxSize(sectionIndex))
03766 << index;
03767
03768 int used = 0;
03769 if (false && sectiontext.trimmed().isEmpty()) {
03770 state = Intermediate;
03771 } else {
03772 switch (sn.type) {
03773 case AmPmSection: {
03774 const int ampm = findAmPm(sectiontext, sectionIndex, &used);
03775 switch (ampm) {
03776 case AM:
03777 case PM:
03778 num = ampm;
03779 state = Acceptable;
03780 break;
03781 case PossibleAM:
03782 case PossiblePM:
03783 num = ampm - 2;
03784 state = Intermediate;
03785 break;
03786 case PossibleBoth:
03787 num = 0;
03788 state = Intermediate;
03789 break;
03790 case Neither:
03791 state = Invalid;
03792 QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1";
03793 break;
03794 default:
03795 QDTPDEBUGN("This should never happen(findAmPm returned %d", ampm);
03796 break;
03797 }
03798 if (state != Invalid) {
03799 QString str = text;
03800 text.replace(index, used, sectiontext.left(used));
03801 }
03802 break;
03803 }
03804 case MonthSection:
03805 case DaySection:
03806 if (sn.count >= 3) {
03807 if (sn.type == MonthSection) {
03808 num = findMonth(sectiontext.toLower(), 1, sectionIndex, §iontext, &used);
03809 } else {
03810 num = findDay(sectiontext.toLower(), 1, sectionIndex, §iontext, &used);
03811 }
03812
03813 if (num != -1) {
03814 state = (used == sectiontext.size() ? Acceptable : Intermediate);
03815 QString str = text;
03816 text.replace(index, used, sectiontext.left(used));
03817 } else {
03818 state = Intermediate;
03819 }
03820 break;
03821 }
03822
03823 case YearSection:
03824 case Hour12Section:
03825 case Hour24Section:
03826 case MinuteSection:
03827 case SecondSection:
03828 case MSecSection: {
03829 if (sectiontext.isEmpty()) {
03830 num = 0;
03831 used = 0;
03832 state = Intermediate;
03833 } else {
03834 const int absMax = absoluteMax(sectionIndex);
03835 QLocale loc;
03836 bool ok = true;
03837 int last = -1;
03838 used = -1;
03839
03840 const int max = qMin(sectionMaxSize(sectionIndex), sectiontext.size());
03841 for (int digits=1; digits<=max; ++digits) {
03842 if (sectiontext.at(digits - 1).isSpace())
03843 break;
03844 int tmp = (int)loc.toUInt(sectiontext.left(digits), &ok, 10);
03845 if (ok && sn.type == Hour12Section) {
03846 if (tmp > 12) {
03847 tmp = -1;
03848 ok = false;
03849 } else if (tmp == 12) {
03850 tmp = 0;
03851 }
03852 }
03853 if (ok && tmp <= absMax) {
03854 QDTPDEBUG << sectiontext.left(digits) << tmp << digits;
03855 last = tmp;
03856 used = digits;
03857 } else {
03858 break;
03859 }
03860 }
03861 if (last == -1) {
03862 const QChar &first = sectiontext.at(0);
03863 if (separators.at(sectionIndex + 1).startsWith(first)) {
03864 used = 0;
03865 state = Intermediate;
03866 } else {
03867 state = Invalid;
03868 QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok;
03869 }
03870 } else {
03871 num += last;
03872 const bool done = (used == sectionMaxSize(sectionIndex));
03873 if (num < absoluteMin(sectionIndex)) {
03874 state = done ? Invalid : Intermediate;
03875 if (done)
03876 QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absoluteMin(sectionIndex);
03877 } else if (num > absMax) {
03878 state = Intermediate;
03879 } else if (!done && (fieldInfo(sectionIndex) & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
03880 state = Intermediate;
03881 } else {
03882 state = Acceptable;
03883 }
03884 }
03885 }
03886 break; }
03887 default: qFatal("NoSection or Internal. This should never happen"); break;
03888 }
03889 }
03890
03891 if (usedptr)
03892 *usedptr = used;
03893
03894 return (state != Invalid ? num : -1);
03895 }
03896 #endif // QT_NO_TEXTDATE
03897
03898 #ifndef QT_NO_DATESTRING
03899
03903 QDateTimeParser::StateNode QDateTimeParser::parse(const QString &inp,
03904 const QVariant ¤tValue, bool fixup) const
03905 {
03906 QString input = inp;
03907 State state = Acceptable;
03908 const QVariant maximum = getMaximum();
03909 const QVariant minimum = getMinimum();
03910
03911 QVariant tmp;
03912 SectionNode sn = {NoSection, 0, false};
03913 int pos = 0;
03914 bool conflicts = false;
03915
03916
03917 {
03918 int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits;
03919 const QDateTime &dt = currentValue.toDateTime();
03920 year = dt.date().year();
03921 year2digits = year % 100;
03922 month = dt.date().month();
03923 day = dt.date().day();
03924 hour = dt.time().hour();
03925 hour12 = -1;
03926 minute = dt.time().minute();
03927 second = dt.time().second();
03928 msec = dt.time().msec();
03929 dayofweek = dt.date().dayOfWeek();
03930 ampm = -1;
03931 QSet<int*> isSet;
03932 int num;
03933 State tmpstate;
03934 int *current;
03935
03936 state = Acceptable;
03937
03938 for (int index=0; state != Invalid && index<sectionNodes.size(); ++index) {
03939 QString sep = input.mid(pos, separators.at(index).size());
03940
03941 if (sep != separators.at(index)) {
03942 QDTPDEBUG << "invalid because" << sep << "!=" << separators.at(index)
03943 << index << pos << currentSectionIndex;
03944 state = Invalid;
03945 goto end;
03946 }
03947 pos += separators.at(index).size();
03948 sectionNodes[index].pos = pos;
03949 current = 0;
03950 sn = sectionNodes.at(index);
03951 int used;
03952
03953 num = parseSection(index, input, pos, tmpstate, &used);
03954 QDTPDEBUG << "sectionValue" << sectionName(sectionType(index)) << input
03955 << "pos" << pos << "used" << used << stateName(tmpstate);
03956 if (fixup && tmpstate == Intermediate && (fieldInfo(index) & (Numeric|FixedWidth)) == (Numeric|FixedWidth) && used < sn.count) {
03957 input.insert(pos, QString().fill(QLatin1Char('0'), sn.count - used));
03958 num = parseSection(index, input, pos, tmpstate, &used);
03959 }
03960 pos += qMax(0, used);
03961
03962 state = qMin<State>(state, tmpstate);
03963 QDTPDEBUG << index << sectionName(sectionType(index)) << "is set to"
03964 << pos << "state is" << stateName(state);
03965
03966
03967 if (state != Invalid) {
03968 switch (sn.type) {
03969 case Hour24Section: current = &hour; break;
03970 case Hour12Section: current = &hour12; break;
03971 case MinuteSection: current = &minute; break;
03972 case SecondSection: current = &second; break;
03973 case MSecSection: current = &msec; break;
03974 case YearSection:
03975 if (sn.count == 2) {
03976 current = &year2digits;
03977 } else {
03978 current = &year;
03979 }
03980 break;
03981 case MonthSection: current = &month; break;
03982 case DaySection:
03983 if (sn.count >= 3) {
03984 current = &dayofweek;
03985 } else {
03986 current = &day; num = qMax<int>(1, num);
03987 }
03988 break;
03989 case AmPmSection: current = &m; break;
03990 default:
03991 qFatal("%s found in sections validateAndInterpret. This should never happen",
03992 sectionName(sn.type).toLatin1().constData());
03993 break;
03994 }
03995 Q_ASSERT(current);
03996 if (isSet.contains(current) && *current != num) {
03997 QDTPDEBUG << "CONFLICT " << sectionName(sn.type) << *current << num;
03998 conflicts = true;
03999 if (index != currentSectionIndex || num == -1) {
04000 continue;
04001 }
04002 }
04003 if (num != -1)
04004 *current = num;
04005 isSet.insert(current);
04006 }
04007 }
04008
04009 if (state != Invalid && input.mid(pos) != separators.last()) {
04010 QDTPDEBUG << "1invalid because" << input.mid(pos)
04011 << "!=" << separators.last() << pos;
04012 state = Invalid;
04013 }
04014
04015 if (state != Invalid) {
04016 if (typ != QVariant::Time) {
04017 if (year % 100 != year2digits) {
04018 if (isSet.contains(&year2digits) && !isSet.contains(&year)) {
04019 year = (year / 100) * 100;
04020 year += year2digits;
04021 } else if (isSet.contains(&year2digits) && isSet.contains(&year)) {
04022 conflicts = true;
04023 SectionNode sn = sectionNode(currentSectionIndex);
04024 if (sn.type == YearSection) {
04025 if (sn.count == 2) {
04026 year = (year / 100) * 100;
04027 year += year2digits;
04028 }
04029 }
04030 }
04031 }
04032
04033 const QDate date = strictDate(year, month, day);
04034 const int diff = dayofweek - date.dayOfWeek() && isSet.contains(&dayofweek);
04035 if (diff != 0 && state == Acceptable) {
04036 conflicts = true;
04037 const SectionNode &sn = sectionNode(currentSectionIndex);
04038 if (sn.type == DaySection && sn.count >= 3) {
04039 day -= diff;
04040 if (day < 0) {
04041 day += 7;
04042 } else if (day > date.daysInMonth()) {
04043 day -= 7;
04044 }
04045 QDTPDEBUG << year << month << day << dayofweek
04046 << diff << strictDate(year, month, day).dayOfWeek();
04047 }
04048 }
04049 bool needfixday = false;
04050 if (sectionType(currentSectionIndex) == DaySection) {
04051 cachedDay = day;
04052 } else if (cachedDay > day) {
04053 day = cachedDay;
04054 needfixday = true;
04055 }
04056
04057 if (!QDate::isValid(year, month, day)) {
04058 if (day < 32) {
04059 cachedDay = day;
04060 }
04061 if (day > 28 && QDate::isValid(year, month, 1)) {
04062 needfixday = true;
04063 }
04064 }
04065 if (needfixday) {
04066 if (state == Acceptable && fixday) {
04067 day = qMin<int>(day, strictDate(year, month, 1).daysInMonth());
04068
04069 const QLocale loc;
04070 for (int i=0; i<sectionNodes.size(); ++i) {
04071 if (sectionType(i) == DaySection) {
04072 input.replace(sectionPos(i), sectionSize(i), loc.toString(day));
04073 }
04074 }
04075 } else {
04076 state = qMin(Intermediate, state);
04077 }
04078
04079 }
04080 }
04081
04082 if (typ != QVariant::Date) {
04083 if (isSet.contains(&hour12)) {
04084 const bool hasHour = isSet.contains(&hour);
04085 if (ampm == -1) {
04086 if (hasHour) {
04087 ampm = (hour < 12 ? 0 : 1);
04088 } else {
04089 ampm = 0;
04090 }
04091 }
04092 hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12);
04093 if (!hasHour) {
04094 hour = hour12;
04095 } else if (hour != hour12) {
04096 conflicts = true;
04097 }
04098 } else if (ampm != -1) {
04099 if (!isSet.contains(&hour)) {
04100 hour = (12 * ampm);
04101 } else if ((ampm == 0) != (hour < 12)) {
04102 conflicts = true;
04103 }
04104 }
04105
04106 }
04107
04108 tmp = QVariant(QDateTime(strictDate(year, month, day), QTime(hour, minute, second, msec)));
04109 QDTPDEBUG << year << month << day << hour << minute << second << msec;
04110
04111 }
04112 QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
04113 tmp.toString().toLatin1().constData(), stateName(state).toLatin1().constData());
04114 }
04115 end:
04116 if (tmp.toDateTime().isValid()) {
04117 if (state != Invalid && dateTimeCompare(tmp, minimum) < 0) {
04118 state = checkIntermediate(tmp.toDateTime(), input);
04119 } else {
04120 if (dateTimeCompare(tmp, maximum) > 0)
04121 state = Invalid;
04122 QDTPDEBUG << "not checking intermediate because tmp is" << tmp << minimum << maximum;
04123 }
04124 }
04125 StateNode node;
04126 node.input = input;
04127 node.state = state;
04128 node.conflicts = conflicts;
04129 node.value = tmp;
04130 text = input;
04131 return node;
04132 }
04133 #endif // QT_NO_DATESTRING
04134
04135 #ifndef QT_NO_TEXTDATE
04136
04141 int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex, QString *usedMonth, int *used) const
04142 {
04143 int bestMatch = -1;
04144 int bestCount = 0;
04145 if (!str1.isEmpty()) {
04146 const SectionNode sn = sectionNode(sectionIndex);
04147 Q_ASSERT(sn.type == MonthSection);
04148 QString(*nameFunction)(int) = sn.count == 3
04149 ? &QDate::shortMonthName
04150 : &QDate::longMonthName;
04151
04152 for (int month=startMonth; month<=12; ++month) {
04153 for (int attempt=0; attempt<(sn.count == 3 ? 2 : 1); ++attempt) {
04154 QString str2;
04155 if (attempt == 0) {
04156 str2 = nameFunction(month).toLower();
04157 } else {
04158 str2 = QString::fromAscii(qt_shortMonthNames[month - 1]).toLower();
04159 }
04160
04161 if (str1.startsWith(str2)) {
04162 if (used) {
04163 QDTPDEBUG << "used is set to" << str2.size();
04164 *used = str2.size();
04165 }
04166 if (usedMonth)
04167 *usedMonth = nameFunction(month);
04168 return month;
04169 }
04170
04171 const int limit = qMin(str1.size(), str2.size());
04172
04173 QDTPDEBUG << "limit is" << limit << str1 << str2;
04174 bool found = true;
04175 for (int i=0; i<limit; ++i) {
04176 if (str1.at(i) != str2.at(i)) {
04177 if (i > bestCount) {
04178 bestCount = i;
04179 bestMatch = month;
04180 }
04181 found = false;
04182 break;
04183 }
04184
04185 }
04186 if (found) {
04187 if (used) {
04188 *used = limit;
04189 }
04190 if (usedMonth)
04191 *usedMonth = nameFunction(month);
04192 QDTPDEBUG << "used is set to" << limit << *usedMonth;
04193
04194 return month;
04195 }
04196 }
04197 }
04198 if (usedMonth && bestMatch != -1)
04199 *usedMonth = nameFunction(bestMatch);
04200
04201 }
04202 if (used) {
04203 QDTPDEBUG << "used is set to" << bestCount;
04204 *used = bestCount;
04205 }
04206 return bestMatch;
04207 }
04208
04209 int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const
04210 {
04211 int bestMatch = -1;
04212 int bestCount = 0;
04213 if (!str1.isEmpty()) {
04214 const SectionNode sn = sectionNode(sectionIndex);
04215 Q_ASSERT(sn.type == DaySection);
04216 QString(*nameFunction)(int) = sn.count == 3
04217 ? &QDate::shortDayName
04218 : &QDate::longDayName;
04219
04220 for (int day=startDay; day<=7; ++day) {
04221 const QString str2 = nameFunction(day).toLower();
04222
04223 if (str1.startsWith(str2)) {
04224 if (used)
04225 *used = str2.size();
04226 if (usedDay)
04227 *usedDay = nameFunction(day);
04228 return day;
04229 }
04230
04231 const int limit = qMin(str1.size(), str2.size());
04232 bool found = true;
04233 for (int i=0; i<limit; ++i) {
04234 if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) {
04235 if (i > bestCount) {
04236 bestCount = i;
04237 bestMatch = day;
04238 }
04239 found = false;
04240 break;
04241 }
04242
04243 }
04244 if (found) {
04245 if (used)
04246 *used = limit;
04247 if (usedDay)
04248 *usedDay = nameFunction(day);
04249
04250 return day;
04251 }
04252 }
04253 if (usedDay && bestMatch != -1)
04254 *usedDay = nameFunction(bestMatch);
04255 }
04256 if (used)
04257 *used = bestCount;
04258
04259 return bestMatch;
04260 }
04261 #endif // QT_NO_TEXTDATE
04262
04276 int QDateTimeParser::findAmPm(QString &str, int index, int *used) const
04277 {
04278 const SectionNode s = sectionNode(index);
04279 Q_ASSERT(s.type == AmPmSection);
04280 if (used)
04281 *used = str.size();
04282 if (str.trimmed().isEmpty()) {
04283 return PossibleBoth;
04284 }
04285 const QLatin1Char space(' ');
04286 int size = sectionMaxSize(index);
04287
04288 enum {
04289 amindex = 0,
04290 pmindex = 1
04291 };
04292 QString ampm[2];
04293 ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase);
04294 ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase);
04295 for (int i=0; i<2; ++i)
04296 ampm[i].truncate(size);
04297
04298 QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
04299
04300 if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) {
04301 str = ampm[amindex];
04302 return AM;
04303 } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) {
04304 str = ampm[pmindex];
04305 return PM;
04306 } else if (str.count(space) == 0 && str.size() >= size) {
04307 return Neither;
04308 }
04309 size = qMin(size, str.size());
04310
04311 bool broken[2] = {false, false};
04312 for (int i=0; i<size; ++i) {
04313 if (str.at(i) != space) {
04314 for (int j=0; j<2; ++j) {
04315 if (!broken[j]) {
04316 int index = ampm[j].indexOf(str.at(i));
04317 QDTPDEBUG << "looking for" << str.at(i)
04318 << "in" << ampm[j] << "and got" << index;
04319 if (index == -1) {
04320 if (str.at(i).category() == QChar::Letter_Uppercase) {
04321 index = ampm[j].indexOf(str.at(i).toLower());
04322 QDTPDEBUG << "trying with" << str.at(i).toLower()
04323 << "in" << ampm[j] << "and got" << index;
04324 } else if (str.at(i).category() == QChar::Letter_Lowercase) {
04325 index = ampm[j].indexOf(str.at(i).toUpper());
04326 QDTPDEBUG << "trying with" << str.at(i).toUpper()
04327 << "in" << ampm[j] << "and got" << index;
04328 }
04329 if (index == -1) {
04330 broken[j] = true;
04331 if (broken[amindex] && broken[pmindex]) {
04332 QDTPDEBUG << str << "didn't make it";
04333 return Neither;
04334 }
04335 continue;
04336 } else {
04337 str[i] = ampm[j].at(index);
04338 }
04339 }
04340 ampm[j].remove(index, 1);
04341 }
04342 }
04343 }
04344 }
04345 if (!broken[pmindex] && !broken[amindex])
04346 return PossibleBoth;
04347 return (!broken[amindex] ? PossibleAM : PossiblePM);
04348 }
04349
04355 int QDateTimeParser::maxChange(int index) const
04356 {
04357 const SectionNode sn = sectionNode(index);
04358 switch (sn.type) {
04359
04360 case MSecSection: return 999;
04361 case SecondSection: return 59 * 1000;
04362 case MinuteSection: return 59 * 60 * 1000;
04363 case Hour24Section: case Hour12Section: return 59 * 60 * 60 * 1000;
04364
04365
04366 case DaySection: return 30;
04367 case MonthSection: return 365 - 31;
04368 case YearSection: return sn.count == 2
04369 ? 100 * 365
04370 : 9999 * 365;
04371 default: qFatal("%s passed to maxChange. This should never happen", sectionName(sectionType(index)).toLatin1().constData());
04372 }
04373 return -1;
04374 }
04375
04376 QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
04377 {
04378 FieldInfo ret = 0;
04379 const SectionNode sn = sectionNode(index);
04380 const Section s = sn.type;
04381 switch (s) {
04382 case MSecSection:
04383 case SecondSection:
04384 case MinuteSection:
04385 case Hour24Section:
04386 case Hour12Section:
04387 case YearSection:
04388 ret |= Numeric;
04389 if (s != YearSection) {
04390 ret |= AllowPartial;
04391 }
04392 if (sn.count != 1) {
04393 ret |= FixedWidth;
04394 }
04395 break;
04396 case MonthSection:
04397 case DaySection:
04398 switch (sn.count) {
04399 case 2:
04400 ret |= FixedWidth;
04401 case 1:
04402 ret |= (Numeric|AllowPartial);
04403 break;
04404 case 3:
04405 ret |= FixedWidth;
04406 break;
04407 case 4:
04408 break;
04409 default: qFatal("This should not happen %d %s %d",
04410 index, qPrintable(sectionName(sn.type)), sn.count);
04411 break;
04412 }
04413 break;
04414 case AmPmSection:
04415 ret |= FixedWidth;
04416 break;
04417 default: qFatal("This should not happen %d %s",
04418 index, qPrintable(sectionName(sn.type)));
04419 }
04420 return ret;
04421 }
04422
04423
04424
04425
04432 QString QDateTimeParser::sectionFormat(int index) const
04433 {
04434 const SectionNode sn = sectionNode(index);
04435 return sectionFormat(sn.type, sn.count);
04436 }
04437
04438 QString QDateTimeParser::sectionFormat(Section s, int count) const
04439 {
04440 QChar fillChar;
04441 switch (s) {
04442 case AmPmSection: return count == 1 ? QLatin1String("AP") : QLatin1String("ap");
04443 case MSecSection: fillChar = QLatin1Char('z'); break;
04444 case SecondSection: fillChar = QLatin1Char('s'); break;
04445 case MinuteSection: fillChar = QLatin1Char('m'); break;
04446 case Hour24Section: fillChar = QLatin1Char('H'); break;
04447 case Hour12Section: fillChar = QLatin1Char('h'); break;
04448 case DaySection: fillChar = QLatin1Char('d'); break;
04449 case MonthSection: fillChar = QLatin1Char('M'); break;
04450 case YearSection: fillChar = QLatin1Char('y'); break;
04451 default:
04452 qFatal("%s passed to sectionFormat. This should never happen", sectionName(s).toLatin1().constData());
04453 return QString();
04454 }
04455 Q_ASSERT(!fillChar.isNull());
04456 QString str;
04457 str.fill(fillChar, count);
04458 return str;
04459 }
04460
04466 int QDateTimeParser::potentialValue(const QString &str, int min, int max, int index,
04467 const QVariant ¤tValue, int insert) const
04468 {
04469 const SectionNode sn = sectionNode(index);
04470
04471 int size = sectionMaxSize(index);
04472 const int add = (sn.type == YearSection && sn.count == 2) ? currentValue.toDate().year() % 100 : 0;
04473 min -= add;
04474 max -= add;
04475
04476 const QString simplified = str.simplified();
04477 if (simplified.isEmpty()) {
04478 return min + add;
04479 } else if (simplified.toInt() > max && max >= 0) {
04480 return -1;
04481 }
04482
04483 const int ret = potentialValueHelper(simplified, min, max, size, insert);
04484 if (ret == -1)
04485 return -1;
04486 return ret + add;
04487 }
04488
04493 int QDateTimeParser::potentialValueHelper(const QString &str, int min, int max, int size, int insert) const
04494 {
04495 if (str.size() == size) {
04496 const int val = str.toInt();
04497 if (val < min || val > max)
04498 return -1;
04499 QDTPDEBUG << "SUCCESS" << val << "is >=" << min << "and <=" << max;
04500 return val;
04501 }
04502
04503 for (int i=0; i<=str.size(); ++i) {
04504 for (int j=0; j<10; ++j) {
04505 int ret = potentialValueHelper(str + QLatin1Char('0' + j), min, max, size, insert);
04506 if (ret != -1) {
04507 return ret;
04508 } else if (insert >= 0) {
04509 QString tmp = str;
04510 tmp.insert(insert, QLatin1Char('0' + j));
04511 ret = potentialValueHelper(tmp, min, max, size, insert);
04512 if (ret != -1)
04513 return ret;
04514 }
04515 }
04516 }
04517 return -1;
04518 }
04519
04520 #ifndef QT_NO_DATESTRING
04521
04526 QDateTimeParser::State QDateTimeParser::checkIntermediate(const QDateTime &dt, const QString &s) const
04527 {
04528 const QLatin1Char space(' ');
04529
04530 const QVariant minimum = getMinimum();
04531 const QVariant maximum = getMaximum();
04532 Q_ASSERT(dateTimeCompare(dt, minimum) < 0);
04533
04534 bool found = false;
04535 for (int i=0; i<sectionNodes.size(); ++i) {
04536 const SectionNode &sn = sectionNodes.at(i);
04537 QString t = sectionText(s, i, sn.pos).toLower();
04538 if (t.contains(space) || t.size() < sectionMaxSize(i)) {
04539 found = true;
04540 switch (sn.type) {
04541 case AmPmSection:
04542 switch (findAmPm(t, i)) {
04543 case AM:
04544 case PM: qFatal("%d This should not happen", __LINE__); return Acceptable;
04545 case Neither: return Invalid;
04546 case PossibleAM:
04547 case PossiblePM:
04548 case PossibleBoth: {
04549 const QVariant copy(dt.addSecs(12 * 60 * 60));
04550 if (dateTimeCompare(copy, minimum) >= 0 && dateTimeCompare(copy, maximum) <= 0)
04551 return Intermediate;
04552 return Invalid; }
04553 }
04554 case MonthSection:
04555 if (sn.count >= 3) {
04556 int tmp = dt.date().month();
04557
04558 while ((tmp = findMonth(t, tmp + 1, sn.count)) != -1) {
04559 const QVariant copy(dt.addMonths(tmp - dt.date().month()));
04560 if (dateTimeCompare(copy, minimum) >= 0 && dateTimeCompare(copy, maximum) <= 0)
04561 break;
04562 }
04563 if (tmp == -1) {
04564 return Invalid;
04565 }
04566 }
04567
04568
04569 default: {
04570 int toMin;
04571 int toMax;
04572
04573 if (sn.type & TimeSectionMask) {
04574 if (dt.daysTo(minimum.toDateTime()) != 0) {
04575 QDTPDEBUG << "if (dt.daysTo(minimum.toDateTime()) != 0)" << dt.daysTo(minimum.toDateTime());
04576 return Invalid;
04577 }
04578 toMin = dt.time().msecsTo(minimum.toDateTime().time());
04579 if (dt.daysTo(maximum.toDateTime()) > 0) {
04580 toMax = -1;
04581 } else {
04582 toMax = dt.time().msecsTo(maximum.toDateTime().time());
04583 }
04584 } else {
04585 toMin = dt.daysTo(minimum.toDateTime());
04586 toMax = dt.daysTo(maximum.toDateTime());
04587 }
04588 int maxChange = QDateTimeParser::maxChange(i);
04589 if (toMin > maxChange) {
04590 QDTPDEBUG << "invalid because toMin > maxChange" << toMin
04591 << maxChange << t << dt << minimum.toDateTime();
04592
04593 return Invalid;
04594 } else if (toMax > maxChange) {
04595 toMax = -1;
04596 }
04597
04598 int min = getDigit(minimum, sn.type);
04599 int max = toMax != -1 ? getDigit(maximum, sn.type) : -1;
04600 int pos = cursorPosition() - sn.pos;
04601 if (pos < 0 || pos >= t.size())
04602 pos = -1;
04603 int tmp = potentialValue(t, min, max, i, dt, pos);
04604 QDTPDEBUG << tmp << t << min << max << sectionName(sn.type)
04605 << minimum.toDate() << maximum.toDate();
04606 if (tmp == -1) {
04607 QDTPDEBUG << "invalid because potentialValue(" << t << min << max
04608 << sectionName(sn.type) << "returned" << tmp << toMax;
04609 return Invalid;
04610 } else if (tmp > absoluteMax(i)) {
04611 QDTPDEBUG << "invalid because potentialValue(" << t << min << max
04612 << sectionName(sn.type) << "returned a larger number than absoluteMax" << tmp << absoluteMax(i);
04613 return Invalid;
04614 }
04615
04616 QVariant var(dt);
04617 setDigit(var, sn.type, tmp);
04618 if (dateTimeCompare(var, maximum) > 0) {
04619 QDTPDEBUG << "invalid because" << var.toString() << ">" << maximum.toString();
04620 return Invalid;
04621 }
04622 break; }
04623 }
04624 }
04625 }
04626 return found ? Intermediate : Invalid;
04627 }
04628 #endif // QT_NO_DATESTRING
04629
04635 QString QDateTimeParser::sectionName(int s) const
04636 {
04637 switch (s) {
04638 case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection");
04639 case QDateTimeParser::DaySection: return QLatin1String("DaySection");
04640 case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section");
04641 case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section");
04642 case QDateTimeParser::MSecSection: return QLatin1String("MSecSection");
04643 case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection");
04644 case QDateTimeParser::MonthSection: return QLatin1String("MonthSection");
04645 case QDateTimeParser::SecondSection: return QLatin1String("SecondSection");
04646 case QDateTimeParser::YearSection: return QLatin1String("YearSection");
04647 case QDateTimeParser::NoSection: return QLatin1String("NoSection");
04648 case QDateTimeParser::FirstSection: return QLatin1String("FirstSection");
04649 case QDateTimeParser::LastSection: return QLatin1String("LastSection");
04650 default: return QLatin1String("Unknown section ") + QString::number(s);
04651 }
04652 }
04653
04659 QString QDateTimeParser::stateName(int s) const
04660 {
04661 switch (s) {
04662 case Invalid: return QLatin1String("Invalid");
04663 case Intermediate: return QLatin1String("Intermediate");
04664 case Acceptable: return QLatin1String("Acceptable");
04665 default: return QLatin1String("Unknown state ") + QString::number(s);
04666 }
04667 }
04668
04669 #ifndef QT_NO_DATESTRING
04670 bool QDateTimeParser::fromString(const QString &text, QDate *date, QTime *time) const
04671 {
04672 QVariant val;
04673 if (date && time) {
04674 val = QDateTime(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN);
04675 } else if (date) {
04676 val = QDate(1900, 1, 1);
04677 } else {
04678 Q_ASSERT(time);
04679 val = QDATETIMEEDIT_TIME_MIN;
04680 }
04681 const StateNode tmp = parse(text, val, false);
04682 if (tmp.state != Acceptable || tmp.conflicts) {
04683 return false;
04684 }
04685 if (time) {
04686 const QTime t = tmp.value.toTime();
04687 if (!t.isValid()) {
04688 return false;
04689 }
04690 *time = t;
04691 }
04692
04693 if (date) {
04694 const QDate d = tmp.value.toDate();
04695 if (!d.isValid()) {
04696 return false;
04697 }
04698 *date = d;
04699 }
04700 return true;
04701 }
04702
04703 QVariant QDateTimeParser::getMinimum() const
04704 {
04705 switch (typ) {
04706 case QVariant::Time: return QDATETIMEEDIT_TIME_MIN;
04707 case QVariant::Date: return QDATETIMEEDIT_DATE_MIN;
04708 case QVariant::DateTime: return QDATETIMEEDIT_DATETIME_MIN;
04709 default: break;
04710 }
04711 return QVariant();
04712 }
04713 QVariant QDateTimeParser::getMaximum() const
04714 {
04715 switch (typ) {
04716 case QVariant::Time: return QDATETIMEEDIT_TIME_MAX;
04717 case QVariant::Date: return QDATETIMEEDIT_DATE_MAX;
04718 case QVariant::DateTime: return QDATETIMEEDIT_DATETIME_MAX;
04719 default: break;
04720 }
04721 return QVariant();
04722 }
04723 #endif // QT_NO_DATESTRING
04724
04725 QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
04726 {
04727 if (ap == AmText) {
04728 return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am"));
04729 } else {
04730 return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm"));
04731 }
04732 }
04733
04734
04735
04736
04737
04738
04739
04740 int QDateTimeParser::dateTimeCompare(const QVariant &arg1, const QVariant &arg2)
04741 {
04742 if ((arg1.type() == QVariant::Time && arg2.type() == QVariant::Date)
04743 || (arg1.type() == QVariant::Date && arg2.type() == QVariant::Time)) {
04744 qWarning("QDateTimeParser::dateTimeCompare: Different types (%s vs. %s)",
04745 arg1.typeName(), arg2.typeName());
04746 }
04747 switch (arg2.type()) {
04748 case QVariant::Date:
04749 if (arg1.toDate() == arg2.toDate()) {
04750 return 0;
04751 } else if (arg1.toDate() < arg2.toDate()) {
04752 return -1;
04753 } else {
04754 return 1;
04755 }
04756 case QVariant::Time:
04757 if (arg1.toTime() == arg2.toTime()) {
04758 return 0;
04759 } else if (arg1.toTime() < arg2.toTime()) {
04760 return -1;
04761 } else {
04762 return 1;
04763 }
04764
04765 case QVariant::DateTime:
04766 if (arg1.toDateTime() == arg2.toDateTime()) {
04767 return 0;
04768 } else if (arg1.toDateTime() < arg2.toDateTime()) {
04769 return -1;
04770 } else {
04771 return 1;
04772 }
04773 default: break;
04774 }
04775 qWarning("QDateTimeParser::dateTimeCompare: Unsupported types (%s, %s)",
04776 arg1.typeName(), arg2.typeName());
04777
04778 return -2;
04779 }
04780
04781 bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2)
04782 {
04783 return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count);
04784 }
04785
04786
04787 #endif // QT_BOOTSTRAPPED