Check validity before adding to a QDateTime

QDateTime's addDays(), addMonths() and addYears() neglected to check
for validity before doing their job, with the result that they could
produce "valid" (but wildly inappropriate) results if used on an
invalid date-time.  Added tests for this case (and the boundary).

Change-Id: I7b0d638501cb5d875a678cde213547a83ed7529e
Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2018-06-13 19:12:15 +02:00
parent 2a6f2fe9ef
commit 92f0f99c23
2 changed files with 53 additions and 2 deletions

View File

@ -4154,6 +4154,9 @@ static inline void massageAdjustedDateTime(QDateTimeData &d, QDate date, QTime t
QDateTime QDateTime::addDays(qint64 ndays) const
{
if (isNull())
return QDateTime();
QDateTime dt(*this);
QPair<QDate, QTime> p = getDateTime(d);
massageAdjustedDateTime(dt.d, p.first.addDays(ndays), p.second);
@ -4176,6 +4179,9 @@ QDateTime QDateTime::addDays(qint64 ndays) const
QDateTime QDateTime::addMonths(int nmonths) const
{
if (isNull())
return QDateTime();
QDateTime dt(*this);
QPair<QDate, QTime> p = getDateTime(d);
massageAdjustedDateTime(dt.d, p.first.addMonths(nmonths), p.second);
@ -4198,6 +4204,9 @@ QDateTime QDateTime::addMonths(int nmonths) const
QDateTime QDateTime::addYears(int nyears) const
{
if (isNull())
return QDateTime();
QDateTime dt(*this);
QPair<QDate, QTime> p = getDateTime(d);
massageAdjustedDateTime(dt.d, p.first.addYears(nyears), p.second);

View File

@ -83,6 +83,7 @@ private Q_SLOTS:
void toString_strformat();
#endif
void addDays();
void addInvalid();
void addMonths();
void addMonths_data();
void addYears();
@ -1095,10 +1096,51 @@ void tst_QDateTime::addDays()
dt1 = QDateTime(QDate(1970, 1, 1), QTime(23, 59, 59));
dt2 = dt1.addDays(-1);
QVERIFY(dt2.isValid());
// ### test invalid QDateTime()
}
void tst_QDateTime::addInvalid()
{
QDateTime bad;
QVERIFY(!bad.isValid());
QVERIFY(bad.isNull());
QDateTime offset = bad.addDays(2);
QVERIFY(offset.isNull());
offset = bad.addMonths(-1);
QVERIFY(offset.isNull());
offset = bad.addYears(23);
QVERIFY(offset.isNull());
offset = bad.addSecs(73);
QVERIFY(offset.isNull());
offset = bad.addMSecs(73);
QVERIFY(offset.isNull());
QDateTime bound = QDateTime::fromMSecsSinceEpoch(std::numeric_limits<qint64>::min(), Qt::UTC);
QVERIFY(bound.isValid());
offset = bound.addMSecs(-1);
QVERIFY(!offset.isValid());
offset = bound.addSecs(-1);
QVERIFY(!offset.isValid());
offset = bound.addDays(-1);
QVERIFY(!offset.isValid());
offset = bound.addMonths(-1);
QVERIFY(!offset.isValid());
offset = bound.addYears(-1);
QVERIFY(!offset.isValid());
bound.setMSecsSinceEpoch(std::numeric_limits<qint64>::max());
QVERIFY(bound.isValid());
offset = bound.addMSecs(1);
QVERIFY(!offset.isValid());
offset = bound.addSecs(1);
QVERIFY(!offset.isValid());
offset = bound.addDays(1);
QVERIFY(!offset.isValid());
offset = bound.addMonths(1);
QVERIFY(!offset.isValid());
offset = bound.addYears(1);
QVERIFY(!offset.isValid());
}
void tst_QDateTime::addMonths_data()
{