Fix QTimeZone::offsetData() for the case without transitions
A zone without transitions, such as any UTC-based one, would previously return invalid data for the offset data at a given time. The method was documented to be "the equivalent of calling offsetFromUtc(), abbreviation(), etc" but these methods do return sensible data for a zone with no transitions. Furthermore, the backend data() method on which it depends is implemented by all backends, including the UTC one, with no transitions. Fix offsetData() to also return data when no transitions are available. Improve docs. Adapt the checkOffset() test to test offsetData() as well as the various functions to get parts of it. In the process, change that test to use a QTimeZone row instead of its name as a QByteArray, so that we can also have rows for lightweight time representations. Change-Id: I241ecf02a26a228cca972bca5e2db687fe41feb4 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
This commit is contained in:
parent
cded6afa35
commit
9f1252da28
@ -1141,9 +1141,12 @@ bool QTimeZone::isDaylightTime(const QDateTime &atDateTime) const
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the effective offset details at the given \a forDateTime. This is
|
||||
the equivalent of calling offsetFromUtc(), abbreviation(), etc individually but is
|
||||
more efficient.
|
||||
Returns the effective offset details at the given \a forDateTime.
|
||||
|
||||
This is the equivalent of calling abbreviation() and all three offset
|
||||
functions individually but is more efficient. If this data is not available
|
||||
for the given datetime, an invalid OffsetData will be returned with an
|
||||
invalid QDateTime as its \c atUtc.
|
||||
|
||||
This method is only available when feature \c timezone is enabled.
|
||||
|
||||
@ -1163,9 +1166,9 @@ QTimeZone::OffsetData QTimeZone::offsetData(const QDateTime &forDateTime) const
|
||||
Q_UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
} else if (hasTransitions()) {
|
||||
return QTimeZonePrivate::toOffsetData(d->data(forDateTime.toMSecsSinceEpoch()));
|
||||
}
|
||||
if (isValid())
|
||||
return QTimeZonePrivate::toOffsetData(d->data(forDateTime.toMSecsSinceEpoch()));
|
||||
|
||||
return QTimeZonePrivate::invalidOffsetData();
|
||||
}
|
||||
@ -1206,7 +1209,7 @@ bool QTimeZone::hasTransitions() const
|
||||
Transition after it.
|
||||
|
||||
If there is no transition after the given \a afterDateTime then an invalid
|
||||
OffsetData will be returned with an invalid QDateTime.
|
||||
OffsetData will be returned with an invalid QDateTime as its \c atUtc.
|
||||
|
||||
The given \a afterDateTime is exclusive.
|
||||
|
||||
@ -1241,7 +1244,7 @@ QTimeZone::OffsetData QTimeZone::nextTransition(const QDateTime &afterDateTime)
|
||||
Transition before it.
|
||||
|
||||
If there is no transition before the given \a beforeDateTime then an invalid
|
||||
OffsetData will be returned with an invalid QDateTime.
|
||||
OffsetData will be returned with an invalid QDateTime as its \c atUtc.
|
||||
|
||||
The given \a beforeDateTime is exclusive.
|
||||
|
||||
|
@ -777,17 +777,29 @@ void tst_QTimeZone::transitionEachZone()
|
||||
|
||||
void tst_QTimeZone::checkOffset_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("zoneName");
|
||||
QTest::addColumn<QTimeZone>("zone");
|
||||
QTest::addColumn<QDateTime>("when");
|
||||
QTest::addColumn<int>("netOffset");
|
||||
QTest::addColumn<int>("stdOffset");
|
||||
QTest::addColumn<int>("dstOffset");
|
||||
|
||||
const QTimeZone UTC = QTimeZone::UTC;
|
||||
QTest::addRow("UTC")
|
||||
<< UTC << QDate(1970, 1, 1).startOfDay(UTC) << 0 << 0 << 0;
|
||||
const auto east = QTimeZone::fromSecondsAheadOfUtc(28'800); // 8 hours
|
||||
QTest::addRow("UTC+8")
|
||||
<< east << QDate(2000, 2, 29).startOfDay(east) << 28'800 << 28'800 << 0;
|
||||
const auto west = QTimeZone::fromDurationAheadOfUtc(std::chrono::hours{-8});
|
||||
QTest::addRow("UTC-8")
|
||||
<< west << QDate(2100, 2, 28).startOfDay(west) << -28'800 << -28'800 << 0;
|
||||
|
||||
struct {
|
||||
const char *zone, *nick;
|
||||
int year, month, day, hour, min, sec;
|
||||
int std, dst;
|
||||
} table[] = {
|
||||
// Exercise the UTC-backend:
|
||||
{ "UTC", "epoch", 1970, 1, 1, 0, 0, 0, 0, 0 },
|
||||
// Zone with no transitions (QTBUG-74614, QTBUG-74666, when TZ backend uses minimal data)
|
||||
{ "Etc/UTC", "epoch", 1970, 1, 1, 0, 0, 0, 0, 0 },
|
||||
{ "Etc/UTC", "pre_int32", 1901, 12, 13, 20, 45, 51, 0, 0 },
|
||||
@ -799,38 +811,40 @@ void tst_QTimeZone::checkOffset_data()
|
||||
{ "Europe/Kiev", "summer", 2017, 10, 27, 12, 0, 0, 2 * 3600, 3600 },
|
||||
{ "Europe/Kiev", "winter", 2017, 10, 29, 12, 0, 0, 2 * 3600, 0 }
|
||||
};
|
||||
bool lacksRows = true;
|
||||
for (const auto &entry : table) {
|
||||
QTimeZone zone(entry.zone);
|
||||
if (zone.isValid()) {
|
||||
QTest::addRow("%s@%s", entry.zone, entry.nick)
|
||||
<< QByteArray(entry.zone)
|
||||
<< zone
|
||||
<< QDateTime(QDate(entry.year, entry.month, entry.day),
|
||||
QTime(entry.hour, entry.min, entry.sec), zone)
|
||||
<< entry.dst + entry.std << entry.std << entry.dst;
|
||||
lacksRows = false;
|
||||
} else {
|
||||
qWarning("Skipping %s@%s test as zone is invalid", entry.zone, entry.nick);
|
||||
}
|
||||
}
|
||||
if (lacksRows)
|
||||
QSKIP("No valid zone info found, skipping test");
|
||||
}
|
||||
|
||||
void tst_QTimeZone::checkOffset()
|
||||
{
|
||||
QFETCH(QByteArray, zoneName);
|
||||
QFETCH(QTimeZone, zone);
|
||||
QFETCH(QDateTime, when);
|
||||
QFETCH(int, netOffset);
|
||||
QFETCH(int, stdOffset);
|
||||
QFETCH(int, dstOffset);
|
||||
|
||||
QTimeZone zone(zoneName);
|
||||
QVERIFY(zone.isValid()); // It was when _data() added the row !
|
||||
QCOMPARE(zone.offsetFromUtc(when), netOffset);
|
||||
QCOMPARE(zone.standardTimeOffset(when), stdOffset);
|
||||
QCOMPARE(zone.daylightTimeOffset(when), dstOffset);
|
||||
QCOMPARE(zone.isDaylightTime(when), dstOffset != 0);
|
||||
|
||||
// Also test offsetData(), which gets all this data in one go:
|
||||
const auto data = zone.offsetData(when);
|
||||
QCOMPARE(data.atUtc, when);
|
||||
QCOMPARE(data.offsetFromUtc, netOffset);
|
||||
QCOMPARE(data.standardTimeOffset, stdOffset);
|
||||
QCOMPARE(data.daylightTimeOffset, dstOffset);
|
||||
}
|
||||
|
||||
void tst_QTimeZone::availableTimeZoneIds()
|
||||
|
Loading…
Reference in New Issue
Block a user