Convert date-time faithfully in QDateTimeEdit::setDateTime()
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 <paul.wicking@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Konstantin Shegunov <kshegunov@gmail.com>
This commit is contained in:
parent
5b193e3dd4
commit
2a653fde48
@ -53,6 +53,9 @@
|
||||
#include <qlayout.h>
|
||||
#include <qset.h>
|
||||
#include <qstyle.h>
|
||||
#if QT_CONFIG(timezone)
|
||||
#include <QTimeZone>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
@ -109,6 +109,7 @@ public:
|
||||
|
||||
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); }
|
||||
|
||||
|
@ -262,6 +262,8 @@ private slots:
|
||||
void timeSpec();
|
||||
void timeSpecBug();
|
||||
void timeSpecInit();
|
||||
void setDateTime_data();
|
||||
void setDateTime();
|
||||
|
||||
void monthEdgeCase();
|
||||
void setLocale();
|
||||
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user