QDate: make weakly incrementable

It is logical that incrementing a date by 1 results in the following
day (rather than the following month or year). Add the pre- and postfix
increment operators as hidden friends, and declare a difference_type
to be qint64. With these additions, QDate models the
weakly_incrementable concept, allowing for it to be used with
std::views::iota.

For symmetry, although not needed for the weakly_incrementable concept,
also add operator--. One could add operator+/+= for std::chono::days,
but it is neither adding symmetry, nor is it required for a relevant
concept, so not doing that (in this commit).

For QTime (and from that, QDateTime), there is no logical "next";
incrementing by a Planck time (as the smallest unit of time) is not
useful, and anything else is arbitrary.

[ChangeLog][Core][QDate] QDate now models the std::weakly_incrementable
concept by implementing pre- and postfix increment (and decrement)
operators.

Change-Id: I87e68f014834446b6444f23ff0e2f16bdc227a14
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Volker Hilsheimer 2025-09-16 10:06:23 +02:00
parent 7e09a2db4f
commit d9b675de61
3 changed files with 116 additions and 0 deletions

View File

@ -4838,6 +4838,46 @@ QDateTime QDateTime::addDays(qint64 ndays) const
return dt;
}
/*!
\fn QDate &QDate::operator++(QDate &date)
\since 6.11
The prefix \c{++} operator, adds a day to \a date and returns a reference to
the modified date object.
\sa addDays(), operator--()
*/
/*!
\fn QDate QDate::operator++(QDate &date, int)
\since 6.11
The postfix \c{++} operator, adds a day to \a date and returns the copy of
\a date with the previous date.
\sa addDays(), operator--()
*/
/*!
\fn QDate &QDate::operator--(QDate &date)
\since 6.11
The prefix \c{--} operator, subtracts a day from \a date and returns a
reference to the modified date object.
\sa addDays(), operator++()
*/
/*!
\fn QDate QDate::operator--(QDate &date, int)
\since 6.11
The postfix \c{--} operator, subtracts a day from \a date and returns a
reference to the modified date object.
\sa addDays(), operator++()
*/
/*!
Returns a QDateTime object containing a datetime \a nmonths months
later than the datetime of this object (or earlier if \a nmonths

View File

@ -29,6 +29,8 @@ class Q_CORE_EXPORT QDate
{
explicit constexpr QDate(qint64 julianDay) : jd(julianDay) {}
public:
using difference_type = qint64;
constexpr QDate() : jd(nullJd()) {}
QDate(int y, int m, int d);
QDate(int y, int m, int d, QCalendar cal);
@ -211,6 +213,32 @@ private:
{ return Qt::compareThreeWay(lhs.jd, rhs.jd); }
Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QDate)
friend inline QDate &operator++(QDate &date) noexcept
{
date = date.addDays(1);
return date;
}
friend inline QDate &operator--(QDate &date) noexcept
{
date = date.addDays(-1);
return date;
}
friend inline QDate operator++(QDate &date, int) noexcept
{
QDate old = date;
++date;
return old;
}
friend inline QDate operator--(QDate &date, int) noexcept
{
QDate old = date;
--date;
return old;
}
#ifndef QT_NO_DATASTREAM
friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, QDate);
friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &);

View File

@ -65,6 +65,8 @@ private Q_SLOTS:
void julianDaysLimits();
void addDays_data();
void addDays();
void incrementable_data() { addDays_data(); }
void incrementable();
void addMonths_data();
void addMonths();
void addYears_data();
@ -99,6 +101,7 @@ private Q_SLOTS:
#endif
void roundtrip() const;
void qdebug() const;
private:
QDate defDate() const { return QDate(1900, 1, 1); }
@ -892,6 +895,51 @@ void tst_QDate::addDays_data()
QTest::newRow( "invalid" ) << 0 << 0 << 0 << 1 << 0 << 0 << 0;
}
void tst_QDate::incrementable()
{
#ifdef __cpp_concepts
static_assert(std::weakly_incrementable<QDate>);
#endif
QFETCH(int, year);
QFETCH(int, month);
QFETCH(int, day);
QFETCH(int, amountToAdd);
QFETCH(int, expectedYear);
QFETCH(int, expectedMonth);
QFETCH(int, expectedDay);
const QDate dt( year, month, day);
QDate pre = dt;
if (amountToAdd < 0) {
for (int i = amountToAdd; i < 0; ++i)
--pre;
} else {
for (int i = 0; i < amountToAdd; ++i)
++pre;
}
QCOMPARE(pre.year(), expectedYear);
QCOMPARE(pre.month(), expectedMonth);
QCOMPARE(pre.day(), expectedDay);
QDate post = dt;
if (amountToAdd < 0) {
for (int i = amountToAdd; i < 0; ++i)
post--;
} else {
for (int i = 0; i < amountToAdd; ++i)
post++;
}
QCOMPARE(post.year(), expectedYear);
QCOMPARE(post.month(), expectedMonth);
QCOMPARE(post.day(), expectedDay);
}
void tst_QDate::addMonths()
{
QFETCH( int, year );