QDateTime: Add validity checks
authorJohn Layt <jlayt@kde.org>
Sun, 17 Jul 2011 18:30:12 +0000 (19:30 +0100)
committerQt by Nokia <qt-info@nokia.com>
Tue, 31 Jan 2012 03:18:37 +0000 (04:18 +0100)
Check the validity of date/time before attempting to perform maths.

Change-Id: Ia6a2caf07c6c36f7d7fac713a77bc4eb456c6ed6
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
dist/changes-5.0.0
src/corelib/tools/qdatetime.cpp
tests/auto/corelib/tools/qdate/tst_qdate.cpp
tests/auto/corelib/tools/qtime/tst_qtime.cpp

index ad085b3..2bbe8a7 100644 (file)
@@ -236,6 +236,11 @@ QtCore
 
 * QDate, QTime, and QDateTime have undergone important behavioural changes:
   * QDate::setYMD() is deprecated, use QDate::setDate() instead
+  * Most methods now apply strict validity checks and will return appropriate
+    and consistent values when invalid.  For example, QDate::year() will return
+    0 and QDate::shortMonthName() will return QString().
+  * Adding days to a null QDate or seconds to a null QTime will no longer return
+    a valid QDate/QTime.
 
 
 QtGui
index 6430e2c..97bcd58 100644 (file)
@@ -330,11 +330,16 @@ bool QDate::isValid() const
     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.
 
+    Returns 0 if the date is invalid.
+
     \sa month(), day()
 */
 
 int QDate::year() const
 {
+    if (isNull())
+        return 0;
+
     int y;
     getDateFromJulianDay(jd, &y, 0, 0);
     return y;
@@ -359,11 +364,16 @@ int QDate::year() const
     \i 12 = "December"
     \endlist
 
+    Returns 0 if the date is invalid.
+
     \sa year(), day()
 */
 
 int QDate::month() const
 {
+    if (isNull())
+        return 0;
+
     int m;
     getDateFromJulianDay(jd, 0, &m, 0);
     return m;
@@ -372,11 +382,16 @@ int QDate::month() const
 /*!
     Returns the day of the month (1 to 31) of this date.
 
+    Returns 0 if the date is invalid.
+
     \sa year(), month(), dayOfWeek()
 */
 
 int QDate::day() const
 {
+    if (isNull())
+        return 0;
+
     int d;
     getDateFromJulianDay(jd, 0, 0, &d);
     return d;
@@ -385,11 +400,16 @@ int QDate::day() const
 /*!
     Returns the weekday (1 to 7) for this date.
 
+    Returns 0 if the date is invalid.
+
     \sa day(), dayOfYear(), Qt::DayOfWeek
 */
 
 int QDate::dayOfWeek() const
 {
+    if (isNull())
+        return 0;
+
     return (jd % 7) + 1;
 }
 
@@ -397,26 +417,38 @@ int QDate::dayOfWeek() const
     Returns the day of the year (1 to 365 or 366 on leap years) for
     this date.
 
+    Returns 0 if the date is invalid.
+
     \sa day(), dayOfWeek()
 */
 
 int QDate::dayOfYear() const
 {
+    if (isNull())
+        return 0;
+
     return jd - julianDayFromDate(year(), 1, 1) + 1;
 }
 
 /*!
     Returns the number of days in the month (28 to 31) for this date.
 
+    Returns 0 if the date is invalid.
+
     \sa day(), daysInYear()
 */
 
 int QDate::daysInMonth() const
 {
-    int y, m, d;
-    getDateFromJulianDay(jd, &y, &m, &d);
+    if (isNull())
+        return 0;
+
+    int y, m;
+    getDateFromJulianDay(jd, &y, &m, 0);
     if (m == 2 && isLeapYear(y))
         return 29;
+    else if (m < 1 || m > 12)
+        return 0;
     else
         return monthDays[m];
 }
@@ -424,13 +456,18 @@ int QDate::daysInMonth() const
 /*!
     Returns the number of days in the year (365 or 366) for this date.
 
+    Returns 0 if the date is invalid.
+
     \sa day(), daysInMonth()
 */
 
 int QDate::daysInYear() const
 {
-    int y, m, d;
-    getDateFromJulianDay(jd, &y, &m, &d);
+    if (isNull())
+        return 0;
+
+    int y;
+    getDateFromJulianDay(jd, &y, 0, 0);
     return isLeapYear(y) ? 366 : 365;
 }
 
@@ -542,14 +579,16 @@ int QDate::weekNumber(int *yearNumber) const
     The month names will be localized according to the system's locale
     settings.
 
+    Returns an empty string if the date is invalid.
+
     \sa toString(), longMonthName(), shortDayName(), longDayName()
 */
 
 QString QDate::shortMonthName(int month, QDate::MonthNameType type)
 {
-    if (month < 1 || month > 12) {
-        month = 1;
-    }
+    if (month < 1 || month > 12)
+        return QString();
+
     switch (type) {
     case QDate::DateFormat:
         return QLocale::system().monthName(month, QLocale::ShortFormat);
@@ -587,14 +626,16 @@ QString QDate::shortMonthName(int month, QDate::MonthNameType type)
     The month names will be localized according to the system's locale
     settings.
 
+    Returns an empty string if the date is invalid.
+
     \sa toString(), shortMonthName(), shortDayName(), longDayName()
 */
 
 QString QDate::longMonthName(int month, MonthNameType type)
 {
-    if (month < 1 || month > 12) {
-        month = 1;
-    }
+    if (month < 1 || month > 12)
+        return QString();
+
     switch (type) {
     case QDate::DateFormat:
         return QLocale::system().monthName(month, QLocale::LongFormat);
@@ -627,14 +668,16 @@ QString QDate::longMonthName(int month, MonthNameType type)
     The day names will be localized according to the system's locale
     settings.
 
+    Returns an empty string if the date is invalid.
+
     \sa toString(), shortMonthName(), longMonthName(), longDayName()
 */
 
 QString QDate::shortDayName(int weekday, MonthNameType type)
 {
-    if (weekday < 1 || weekday > 7) {
-        weekday = 1;
-    }
+    if (weekday < 1 || weekday > 7)
+        return QString();
+
     switch (type) {
     case QDate::DateFormat:
         return QLocale::system().dayName(weekday, QLocale::ShortFormat);
@@ -667,14 +710,16 @@ QString QDate::shortDayName(int weekday, MonthNameType type)
     The day names will be localized according to the system's locale
     settings.
 
+    Returns an empty string if the date is invalid.
+
     \sa toString(), shortDayName(), shortMonthName(), longMonthName()
 */
 
 QString QDate::longDayName(int weekday, MonthNameType type)
 {
-    if (weekday < 1 || weekday > 7) {
-        weekday = 1;
-    }
+    if (weekday < 1 || weekday > 7)
+        return QString();
+
     switch (type) {
     case QDate::DateFormat:
         return QLocale::system().dayName(weekday, QLocale::LongFormat);
@@ -872,22 +917,39 @@ bool QDate::setDate(int year, int month, int day)
     Extracts the date's year, month, and day, and assigns them to
     *\a year, *\a month, and *\a day. The pointers may be null.
 
+    Returns 0 if the date is invalid.
+
     \sa year(), month(), day(), isValid()
 */
 void QDate::getDate(int *year, int *month, int *day)
 {
-    getDateFromJulianDay(jd, year, month, day);
+    if (isValid()) {
+        getDateFromJulianDay(jd, year, month, day);
+    } else {
+        if (year)
+            *year = 0;
+        if (month)
+            *month = 0;
+        if (day)
+            *day = 0;
+    }
 }
 
 /*!
     Returns a QDate object containing a date \a ndays later than the
     date of this object (or earlier if \a ndays is negative).
 
+    Returns a null date if the current date is invalid or the new date is
+    out-of-range.
+
     \sa addMonths() addYears() daysTo()
 */
 
 QDate QDate::addDays(int ndays) const
 {
+    if (isNull())
+        return QDate();
+
     QDate d;
     // this is basically "d.jd = jd + ndays" with checks for integer overflow
     if (ndays >= 0)
@@ -1002,6 +1064,8 @@ QDate QDate::addYears(int nyears) const
     Returns the number of days from this date to \a d (which is
     negative if \a d is earlier than this date).
 
+    Returns 0 if either date is invalid.
+
     Example:
     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 0
 
@@ -1010,6 +1074,9 @@ QDate QDate::addYears(int nyears) const
 
 int QDate::daysTo(const QDate &d) const
 {
+    if (isNull() || d.isNull())
+        return 0;
+
     return d.jd - jd;
 }
 
@@ -1394,44 +1461,64 @@ bool QTime::isValid() const
 /*!
     Returns the hour part (0 to 23) of the time.
 
+    Returns -1 if the time is invalid.
+
     \sa minute(), second(), msec()
 */
 
 int QTime::hour() const
 {
+    if (!isValid())
+        return -1;
+
     return ds() / MSECS_PER_HOUR;
 }
 
 /*!
     Returns the minute part (0 to 59) of the time.
 
+    Returns -1 if the time is invalid.
+
     \sa hour(), second(), msec()
 */
 
 int QTime::minute() const
 {
+    if (!isValid())
+        return -1;
+
     return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
 }
 
 /*!
     Returns the second part (0 to 59) of the time.
 
+    Returns -1 if the time is invalid.
+
     \sa hour(), minute(), msec()
 */
 
 int QTime::second() const
 {
+    if (!isValid())
+        return -1;
+
     return (ds() / 1000)%SECS_PER_MIN;
 }
 
 /*!
     Returns the millisecond part (0 to 999) of the time.
 
+    Returns -1 if the time is invalid.
+
     \sa hour(), minute(), second()
 */
 
 int QTime::msec() const
 {
+    if (!isValid())
+        return -1;
+
     return ds() % 1000;
 }
 
@@ -1579,6 +1666,8 @@ bool QTime::setHMS(int h, int m, int s, int ms)
 
     Note that the time will wrap if it passes midnight.
 
+    Returns a null time if this time is invalid.
+
     Example:
 
     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 5
@@ -1601,11 +1690,16 @@ QTime QTime::addSecs(int s) const
 
     secsTo() does not take into account any milliseconds.
 
+    Returns 0 if either time is invalid.
+
     \sa addSecs(), QDateTime::secsTo()
 */
 
 int QTime::secsTo(const QTime &t) const
 {
+    if (!isValid() || !t.isValid())
+        return 0;
+
     return (t.ds() - ds()) / 1000;
 }
 
@@ -1616,18 +1710,22 @@ int QTime::secsTo(const QTime &t) const
     Note that the time will wrap if it passes midnight. See addSecs()
     for an example.
 
+    Returns a null time if this time is invalid.
+
     \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 (isValid()) {
+        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)
@@ -1645,11 +1743,15 @@ QTime QTime::addMSecs(int ms) const
     seconds in a day, the result is always between -86400000 and
     86400000 ms.
 
+    Returns 0 if either time is invalid.
+
     \sa secsTo(), addMSecs(), QDateTime::msecsTo()
 */
 
 int QTime::msecsTo(const QTime &t) const
 {
+    if (!isValid() || !t.isValid())
+        return 0;
 #if defined(Q_OS_WINCE)
     // GetLocalTime() for Windows CE has no milliseconds resolution
     if (t.startTick > NullTime && startTick > NullTime)
@@ -2260,7 +2362,7 @@ qint64 QDateTime::toMSecsSinceEpoch() const
     QTime utcTime;
     d->getUTC(utcDate, utcTime);
 
-    return toMSecsSinceEpoch_helper(utcDate.jd, utcTime.ds());
+    return toMSecsSinceEpoch_helper(utcDate.toJulianDay(), QTime(0, 0, 0).msecsTo(utcTime));
 }
 
 /*!
@@ -2322,7 +2424,7 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs)
     }
 
     d->date = QDate(1970, 1, 1).addDays(ddays);
-    d->time = QTime().addMSecs(msecs);
+    d->time = QTime(0, 0, 0).addMSecs(msecs);
     d->spec = QDateTimePrivate::UTC;
 
     if (oldSpec != QDateTimePrivate::UTC)
@@ -2347,7 +2449,7 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
     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->time = QTime(0, 0, 0).addSecs(secsSince1Jan1970UTC % SECS_PER_DAY);
     d->spec = QDateTimePrivate::UTC;
 
     if (oldSpec != QDateTimePrivate::UTC)
@@ -2605,8 +2707,8 @@ QDateTime QDateTimePrivate::addMSecs(const QDateTime &dt, qint64 msecs)
  */
 void QDateTimePrivate::addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs)
 {
-    uint dd = utcDate.jd;
-    int tt = utcTime.ds();
+    int dd = utcDate.toJulianDay();
+    int tt = QTime(0, 0, 0).msecsTo(utcTime);
     int sign = 1;
     if (msecs < 0) {
         msecs = -msecs;
@@ -2628,8 +2730,8 @@ void QDateTimePrivate::addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs)
         tt = tt % MSECS_PER_DAY;
     }
 
-    utcDate.jd = dd;
-    utcTime.mds = tt;
+    utcDate = QDate::fromJulianDay(dd);
+    utcTime = QTime(0, 0, 0).addMSecs(tt);
 }
 
 /*!
@@ -2679,6 +2781,8 @@ int QDateTime::daysTo(const QDateTime &other) const
     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.
 
+    Returns 0 if either time is invalid.
+
     Example:
     \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 11
 
@@ -2687,6 +2791,9 @@ int QDateTime::daysTo(const QDateTime &other) const
 
 int QDateTime::secsTo(const QDateTime &other) const
 {
+    if (!isValid() || !other.isValid())
+        return 0;
+
     QDate date1, date2;
     QTime time1, time2;
 
@@ -2705,11 +2812,16 @@ int QDateTime::secsTo(const QDateTime &other) const
     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.
 
+    Returns 0 if either time is null.
+
     \sa addMSecs(), daysTo(), QTime::msecsTo()
 */
 
 qint64 QDateTime::msecsTo(const QDateTime &other) const
 {
+    if (!isValid() || !other.isValid())
+        return 0;
+
     QDate selfDate;
     QDate otherDate;
     QTime selfTime;
@@ -2873,7 +2985,7 @@ QTime QTime::currentTime()
     SYSTEMTIME st;
     memset(&st, 0, sizeof(SYSTEMTIME));
     GetLocalTime(&st);
-    ct.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
+    ct.setHMS(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
 #if defined(Q_OS_WINCE)
     ct.startTick = GetTickCount() % MSECS_PER_DAY;
 #endif
@@ -3780,7 +3892,7 @@ 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;
+    time_t secsSince1Jan1970UTC = toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime(0, 0, 0).msecsTo(time)) / 1000;
     tm *brokenDown = 0;
 
 #if defined(Q_OS_WINCE)
index e1f310d..72c3535 100644 (file)
@@ -168,12 +168,24 @@ void tst_QDate::isValid()
     QFETCH(int, year);
     QFETCH(int, month);
     QFETCH(int, day);
+    QFETCH(uint, jd);
+    QFETCH(bool, valid);
 
-    QTEST(QDate::isValid(year, month, day), "valid");
+    QCOMPARE(QDate::isValid(year, month, day), valid);
 
     QDate d;
     d.setDate(year, month, day);
-    QTEST(d.isValid(), "valid");
+    QCOMPARE(d.isValid(), valid);
+
+    if (valid) {
+        QCOMPARE(d.year(), year);
+        QCOMPARE(d.month(), month);
+        QCOMPARE(d.day(), day);
+    } else {
+        QCOMPARE(d.year(), 0);
+        QCOMPARE(d.month(), 0);
+        QCOMPARE(d.day(), 0);
+    }
 }
 
 void tst_QDate::julianDay_data()
@@ -209,6 +221,7 @@ void tst_QDate::dayOfWeek_data()
     QTest::addColumn<int>("day");
     QTest::addColumn<int>("dayOfWeek");
 
+    QTest::newRow("data0")  <<     0 <<  0 <<  0 << 0;
     QTest::newRow("data1")  <<  2000 <<  1 <<  3 << 1;
     QTest::newRow("data2")  <<  2000 <<  1 <<  4 << 2;
     QTest::newRow("data3")  <<  2000 <<  1 <<  5 << 3;
@@ -241,6 +254,7 @@ void tst_QDate::dayOfYear_data()
     QTest::addColumn<int>("day");
     QTest::addColumn<int>("dayOfYear");
 
+    QTest::newRow("data0")  <<     0 <<  0 <<  0 <<   0;
     QTest::newRow("data1")  <<  2000 <<  1 <<  1 <<   1;
     QTest::newRow("data2")  <<  2000 <<  1 <<  2 <<   2;
     QTest::newRow("data3")  <<  2000 <<  1 <<  3 <<   3;
@@ -274,6 +288,7 @@ void tst_QDate::daysInMonth_data()
     QTest::addColumn<int>("day");
     QTest::addColumn<int>("daysInMonth");
 
+    QTest::newRow("data0")  <<     0 <<  0 <<  0 <<   0;
     QTest::newRow("data1")  <<  2000 <<  1 <<  1 <<  31;
     QTest::newRow("data2")  <<  2000 <<  2 <<  1 <<  29;
     QTest::newRow("data3")  <<  2000 <<  3 <<  1 <<  31;
@@ -320,6 +335,11 @@ void tst_QDate::getDate()
     QCOMPARE(y, 2000);
     QCOMPARE(m, 1);
     QCOMPARE(d, 1);
+    dt.setDate(0, 0, 0);
+    dt.getDate(&y, &m, &d);
+    QCOMPARE(y, 0);
+    QCOMPARE(m, 0);
+    QCOMPARE(d, 0);
 }
 
 void tst_QDate::weekNumber_data()
@@ -537,6 +557,11 @@ void tst_QDate::daysTo()
     QDate dt2(2000, 1, 5);
     QCOMPARE(dt1.daysTo(dt2),  4);
     QCOMPARE(dt2.daysTo(dt1), -4);
+    dt1.setDate(0, 0, 0);
+    QCOMPARE(dt1.daysTo(dt2),  0);
+    dt1.setDate(2000, 1, 1);
+    dt2.setDate(0, 0, 0);
+    QCOMPARE(dt1.daysTo(dt2),  0);
 }
 
 void tst_QDate::operator_eq_eq()
@@ -916,6 +941,8 @@ void tst_QDate::roundtripGermanLocale() const
 
 void tst_QDate::shortDayName() const
 {
+    QCOMPARE(QDate::shortDayName(0), QString());
+
     if (QLocale::system().language() == QLocale::C) {
         QCOMPARE(QDate::shortDayName(1), QLatin1String("Mon"));
         QCOMPARE(QDate::shortDayName(7), QLatin1String("Sun"));
@@ -929,6 +956,8 @@ void tst_QDate::shortDayName() const
 
 void tst_QDate::standaloneShortDayName() const
 {
+    QCOMPARE(QDate::shortDayName(0, QDate::StandaloneFormat), QString());
+
     if (QLocale::system().language() == QLocale::C) {
         QCOMPARE(QDate::shortDayName(1, QDate::StandaloneFormat), QLatin1String("Mon"));
         QCOMPARE(QDate::shortDayName(7, QDate::StandaloneFormat), QLatin1String("Sun"));
@@ -942,6 +971,8 @@ void tst_QDate::standaloneShortDayName() const
 
 void tst_QDate::longDayName() const
 {
+    QCOMPARE(QDate::longDayName(0), QString());
+
     if (QLocale::system().language() == QLocale::C) {
         QCOMPARE(QDate::longDayName(1), QLatin1String("Monday"));
         QCOMPARE(QDate::longDayName(7), QLatin1String("Sunday"));
@@ -955,6 +986,8 @@ void tst_QDate::longDayName() const
 
 void tst_QDate::standaloneLongDayName() const
 {
+    QCOMPARE(QDate::longDayName(0, QDate::StandaloneFormat), QString());
+
     if (QLocale::system().language() == QLocale::C) {
         QCOMPARE(QDate::longDayName(1, QDate::StandaloneFormat), QLatin1String("Monday"));
         QCOMPARE(QDate::longDayName(7, QDate::StandaloneFormat), QLatin1String("Sunday"));
@@ -968,6 +1001,8 @@ void tst_QDate::standaloneLongDayName() const
 
 void tst_QDate::shortMonthName() const
 {
+    QCOMPARE(QDate::shortMonthName(0), QString());
+
     if (QLocale::system().language() == QLocale::C) {
         QCOMPARE(QDate::shortMonthName(1), QLatin1String("Jan"));
         QCOMPARE(QDate::shortMonthName(8), QLatin1String("Aug"));
@@ -981,6 +1016,8 @@ void tst_QDate::shortMonthName() const
 
 void tst_QDate::standaloneShortMonthName() const
 {
+    QCOMPARE(QDate::shortMonthName(0, QDate::StandaloneFormat), QString());
+
     if (QLocale::system().language() == QLocale::C) {
         QCOMPARE(QDate::shortMonthName(1, QDate::StandaloneFormat), QLatin1String("Jan"));
         QCOMPARE(QDate::shortMonthName(8, QDate::StandaloneFormat), QLatin1String("Aug"));
@@ -994,6 +1031,8 @@ void tst_QDate::standaloneShortMonthName() const
 
 void tst_QDate::longMonthName() const
 {
+    QCOMPARE(QDate::longMonthName(0), QString());
+
     if (QLocale::system().language() == QLocale::C) {
         QCOMPARE(QDate::longMonthName(1), QLatin1String("January"));
         QCOMPARE(QDate::longMonthName(8), QLatin1String("August"));
@@ -1007,6 +1046,8 @@ void tst_QDate::longMonthName() const
 
 void tst_QDate::standaloneLongMonthName() const
 {
+    QCOMPARE(QDate::longMonthName(0, QDate::StandaloneFormat), QString());
+
     if (QLocale::system().language() == QLocale::C) {
         QCOMPARE(QDate::longMonthName(1, QDate::StandaloneFormat), QLatin1String("January"));
         QCOMPARE(QDate::longMonthName(8, QDate::StandaloneFormat), QLatin1String("August"));
index 846ff49..d8f72df 100644 (file)
@@ -242,6 +242,7 @@ void tst_QTime::hour_data()
     QTest::newRow(  "data2" ) << 1 << 2 << 3 << 4;
     QTest::newRow(  "data3" ) << 2 << 12 << 13 << 65;
     QTest::newRow(  "data4" ) << 23 << 59 << 59 << 999;
+    QTest::newRow(  "data5" ) << -1 << -1 << -1 << -1;
 }
 
 void tst_QTime::hour()
@@ -271,6 +272,7 @@ void tst_QTime::setHMS_data()
     QTest::newRow(  "data4" ) << 23 << 0 << 0;
     QTest::newRow(  "data5" ) << 23 << 59 << 0;
     QTest::newRow(  "data6" ) << 23 << 59 << 59;
+    QTest::newRow(  "data7" ) << -1 << -1 << -1;
 }
 
 void tst_QTime::setHMS()
@@ -296,6 +298,9 @@ void tst_QTime::secsTo_data()
     QTest::newRow(  "data1" ) << QTime(0,0,0) << QTime(0,1,0) << 60;
     QTest::newRow(  "data2" ) << QTime(0,0,0) << QTime(0,10,0) << 600;
     QTest::newRow(  "data3" ) << QTime(0,0,0) << QTime(23,59,59) << 86399;
+    QTest::newRow(  "data4" ) << QTime(-1, -1, -1) << QTime(0, 0, 0) << 0;
+    QTest::newRow(  "data5" ) << QTime(0, 0, 0) << QTime(-1, -1, -1) << 0;
+    QTest::newRow(  "data6" ) << QTime(-1, -1, -1) << QTime(-1, -1, -1) << 0;
 }
 
 void tst_QTime::secsTo()
@@ -317,6 +322,9 @@ void tst_QTime::msecsTo_data()
     QTest::newRow(  "data1" ) << QTime(0,0,0,0) << QTime(0,0,1,0) << 1000;
     QTest::newRow(  "data2" ) << QTime(0,0,0,0) << QTime(0,0,10,0) << 10000;
     QTest::newRow(  "data3" ) << QTime(0,0,0,0) << QTime(23,59,59,0) << 86399000;
+    QTest::newRow(  "data4" ) << QTime(-1, -1, -1, -1) << QTime(0, 0, 0, 0) << 0;
+    QTest::newRow(  "data5" ) << QTime(0, 0, 0, 0) << QTime(-1, -1, -1, -1) << 0;
+    QTest::newRow(  "data6" ) << QTime(-1, -1, -1, -1) << QTime(-1, -1, -1, -1) << 0;
 }
 
 void tst_QTime::msecsTo()