Skip to content

Commit

Permalink
Convert date-time faithfully in QDateTimeEdit::setDateTime()
Browse files Browse the repository at this point in the history
Previously, setDateTime() was documented to ignore the new date-time's
time-spec. It used the date and time (determined using that timespec)
with the QDateTimeEdit's configured spec. It is debatable whether that
really counts as ignoring its time-spec. All the same, that's what it
did. Fixing it is a behavior change. Added tests.

[ChangeLog][QtWidgets][QDateTimeEdit] QDateTimeEdit::setDateTime() now
converts the new datetime to the QDateTimeEdit's time-spec, rather
than combining its date and time (determined using the time spec it
came with) with the QDateTimeEdit's date and time.

Fixes: QTBUG-71181
Change-Id: Ibf0bd87723c3957ca00a2199d51d992032ef57ee
Reviewed-by: Paul Wicking <[email protected]>
Reviewed-by: Volker Hilsheimer <[email protected]>
Reviewed-by: Konstantin Shegunov <[email protected]>
  • Loading branch information
ediosyncratic committed Dec 12, 2019
1 parent 5b193e3 commit 2a653fd
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 4 deletions.
33 changes: 29 additions & 4 deletions src/widgets/widgets/qdatetimeedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
#include <qlayout.h>
#include <qset.h>
#include <qstyle.h>
#if QT_CONFIG(timezone)
#include <QTimeZone>
#endif

#include <algorithm>

Expand Down Expand Up @@ -218,8 +221,8 @@ QDateTimeEdit::~QDateTimeEdit()
\property QDateTimeEdit::dateTime
\brief the QDateTime that is set in the QDateTimeEdit
When setting this property the timespec of the QDateTimeEdit remains the same
and the timespec of the new QDateTime is ignored.
When setting this property, the new QDateTime is converted to the timespec of
the QDateTimeEdit, which thus remains unchanged.
By default, this property is set to the start of 2000 CE. It can only be set
to a valid QDateTime value. If any operation causes this property to have an
Expand All @@ -243,11 +246,14 @@ void QDateTimeEdit::setDateTime(const QDateTime &datetime)
{
Q_D(QDateTimeEdit);
if (datetime.isValid()) {
QDateTime when = d->convertTimeSpec(datetime);
Q_ASSERT(when.timeSpec() == d->spec);

d->clearCache();
const QDate date = datetime.date();
const QDate date = when.date();
if (!(d->sections & DateSections_Mask))
setDateRange(date, date);
d->setValue(QDateTime(date, datetime.time(), d->spec), EmitIfChanged);
d->setValue(when, EmitIfChanged);
}
}

Expand Down Expand Up @@ -1706,6 +1712,25 @@ QDateTimeEditPrivate::QDateTimeEditPrivate()
#endif
}

QDateTime QDateTimeEditPrivate::convertTimeSpec(const QDateTime &datetime)
{
Q_ASSERT(value.toDateTime().timeSpec() == spec);
switch (spec) {
case Qt::UTC:
return datetime.toUTC();
case Qt::LocalTime:
return datetime.toLocalTime();
case Qt::OffsetFromUTC:
return datetime.toOffsetFromUtc(value.toDateTime().offsetFromUtc());
#if QT_CONFIG(timezone)
case Qt::TimeZone:
return datetime.toTimeZone(value.toDateTime().timeZone());
#endif
}
Q_UNREACHABLE();
}

// FIXME: architecturaly incompatible with OffsetFromUTC or TimeZone as spec (QTBUG-80417).
void QDateTimeEditPrivate::updateTimeSpec()
{
minimum = minimum.toDateTime().toTimeSpec(spec);
Expand Down
1 change: 1 addition & 0 deletions src/widgets/widgets/qdatetimeedit_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class Q_AUTOTEST_EXPORT QDateTimeEditPrivate : public QAbstractSpinBoxPrivate, p

void updateCache(const QVariant &val, const QString &str) const;

QDateTime convertTimeSpec(const QDateTime &datetime);
void updateTimeSpec();
QString valueToText(const QVariant &var) const { return textFromValue(var); }

Expand Down
50 changes: 50 additions & 0 deletions tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ private slots:
void timeSpec();
void timeSpecBug();
void timeSpecInit();
void setDateTime_data();
void setDateTime();

void monthEdgeCase();
void setLocale();
Expand Down Expand Up @@ -3476,6 +3478,54 @@ void tst_QDateTimeEdit::timeSpecInit()
QCOMPARE(widget.dateTime(), utc);
}

void tst_QDateTimeEdit::setDateTime_data()
{
QTest::addColumn<Qt::TimeSpec>("spec");
QDateTime localNoon(QDate(2019, 12, 24), QTime(12, 0), Qt::LocalTime);
#if 0 // Not yet supported
QTest::addColumn<int>("offset");
QTest::addColumn<QByteArray>("zoneName");

QTest::newRow("OffsetFromUTC/LocalTime")
<< Qt::OffsetFromUTC << 7200 << ""
<< localNoon << localNoon.toOffsetFromUtc(7200);
#if QT_CONFIG(timezone)
QTest::newRow("TimeZone/LocalTime")
<< Qt::TimeZone << 0 << "Europe/Berlin"
<< localNoon << localNoon.toTimeZone(QTimeZone("Europe/Berlin"));
#endif
#endif // unsupported
QTest::addColumn<QDateTime>("store");
QTest::addColumn<QDateTime>("expect");
QTest::newRow("LocalTime/LocalTime")
<< Qt::LocalTime // << 0 << ""
<< localNoon << localNoon;
QTest::newRow("LocalTime/UTC")
<< Qt::LocalTime // << 0 << ""
<< localNoon.toUTC() << localNoon;
QTest::newRow("UTC/LocalTime")
<< Qt::UTC // << 0 << ""
<< localNoon << localNoon.toUTC();
QTest::newRow("UTC/UTC")
<< Qt::UTC // << 0 << ""
<< localNoon.toUTC() << localNoon.toUTC();
}

void tst_QDateTimeEdit::setDateTime()
{
QFETCH(const Qt::TimeSpec, spec);
#if 0 // Not yet supported
QFETCH(const int, offset);
QFETCH(const QByteArray, zoneName);
#endif // configuring the spec, when OffsetFromUTC or TimeZone
QFETCH(const QDateTime, store);
QFETCH(const QDateTime, expect);
QDateTimeEdit editor;
editor.setTimeSpec(spec);
editor.setDateTime(store);
QCOMPARE(editor.dateTime(), expect);
}

void tst_QDateTimeEdit::cachedDayTest()
{
testWidget->setDisplayFormat("MM/dd");
Expand Down

0 comments on commit 2a653fd

Please sign in to comment.