Add QTimeZone::aliasMatches()
This makes it possible for the stdCompatibility() test to cope with the backend (based on the Windows Registry, which disagrees with MS's ICU-based std::chrono::tzdb) successfully constructing a zone, by finding a known alias, instead of failing because it doesn't know the name. It may also be useful to client code when dealing with legacy names. Amended some existing tests to only expect what they now should and added some tests specific to aliasMatches(). Also added some explanative comments where it isn't needed. Task-number: QTBUG-115158 Change-Id: I095bdbead78df339e29b29518d5010ef905fa8b2 Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
c464f67db4
commit
e2e5ab0932
@ -829,6 +829,34 @@ QByteArray QTimeZone::id() const
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.8
|
||||
Returns \c true if \a alias is an alternative name for this timezone.
|
||||
|
||||
The IANA (formerly Olson) database has renamed some zones during its
|
||||
history. There are also some zones that only differed prior to 1970 but are
|
||||
now treated as synonymous. Some backends may have data reaching to before
|
||||
1970 and produce distinct zones in the latter case. Others may produce zones
|
||||
indistinguishable except by id(). This method determines whether an ID
|
||||
refers (at least since 1970) to the same zone that this timezone object
|
||||
describes.
|
||||
|
||||
This method is only available when feature \c timezone is enabled.
|
||||
*/
|
||||
bool QTimeZone::aliasMatches(QByteArrayView alias) const
|
||||
{
|
||||
if (alias == id())
|
||||
return true;
|
||||
QByteArray mine = QTimeZonePrivate::aliasToIana(id());
|
||||
// Empty if id() aliases to itself, which we've already checked:
|
||||
if (!mine.isEmpty() && alias == mine)
|
||||
return true;
|
||||
QByteArray its = QTimeZonePrivate::aliasToIana(alias);
|
||||
// Empty if alias aliases to itself, which we've already compared to id()
|
||||
// and, where relevant, mine.
|
||||
return !its.isEmpty() && its == (mine.isEmpty() ? id() : mine);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.2
|
||||
|
||||
|
@ -166,6 +166,7 @@ public:
|
||||
};
|
||||
typedef QList<OffsetData> OffsetDataList;
|
||||
|
||||
bool aliasMatches(QByteArrayView alias) const;
|
||||
QByteArray id() const;
|
||||
QLocale::Territory territory() const;
|
||||
# if QT_DEPRECATED_SINCE(6, 6)
|
||||
|
@ -780,6 +780,9 @@ QByteArray QTimeZonePrivate::aliasToIana(QByteArrayView alias)
|
||||
alias, earlierAliasId);
|
||||
if (data != std::end(aliasMappingTable) && data->aliasId() == alias)
|
||||
return data->ianaId().toByteArray();
|
||||
// Note: empty return means not an alias, which is true of an ID that others
|
||||
// are aliases to, as the table omits self-alias entries. Let caller sort
|
||||
// that out, rather than allocating to return alias.toByteArray().
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <private/qcomparisontesthelper_p.h>
|
||||
|
||||
#include <qlocale.h>
|
||||
#include <qscopeguard.h>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <QOperatingSystemVersion>
|
||||
@ -16,6 +17,8 @@
|
||||
# define USING_WIN_TZ
|
||||
#endif
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
class tst_QTimeZone : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -38,6 +41,8 @@ private Q_SLOTS:
|
||||
void availableTimeZoneIds();
|
||||
void utcOffsetId_data();
|
||||
void utcOffsetId();
|
||||
void aliasMatches_data();
|
||||
void aliasMatches();
|
||||
void specificTransition_data();
|
||||
void specificTransition();
|
||||
void transitionEachZone_data();
|
||||
@ -558,9 +563,12 @@ void tst_QTimeZone::isTimeZoneIdAvailable()
|
||||
const QList<QByteArray> available = QTimeZone::availableTimeZoneIds();
|
||||
for (const QByteArray &id : available) {
|
||||
QVERIFY2(QTimeZone::isTimeZoneIdAvailable(id), id);
|
||||
QVERIFY2(QTimeZone(id).isValid(), id);
|
||||
QCOMPARE(QTimeZone(id).id(), id);
|
||||
const QTimeZone zone(id);
|
||||
QVERIFY2(zone.isValid(), id);
|
||||
QVERIFY2(zone.aliasMatches(id), zone.id() + " != " + id);
|
||||
}
|
||||
// availableTimeZoneIds() doesn't list all possible offset IDs, but
|
||||
// isTimeZoneIdAvailable() should accept them.
|
||||
for (qint32 offset = QTimeZone::MinUtcOffsetSecs;
|
||||
offset <= QTimeZone::MinUtcOffsetSecs; ++offset) {
|
||||
const QByteArray id = QTimeZone(offset).id();
|
||||
@ -700,6 +708,61 @@ void tst_QTimeZone::utcOffsetId()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QTimeZone::aliasMatches_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("iana");
|
||||
QTest::addColumn<QByteArray>("alias");
|
||||
|
||||
QTest::newRow("Montreal=Toronto") << "America/Toronto"_ba << "America/Montreal"_ba;
|
||||
QTest::newRow("Asmera=Asmara") << "Africa/Asmara"_ba << "Africa/Asmera"_ba;
|
||||
QTest::newRow("Argentina/Catamarca")
|
||||
<< "America/Argentina/Catamarca"_ba << "America/Catamarca"_ba;
|
||||
QTest::newRow("Godthab=Nuuk") << "America/Nuuk"_ba << "America/Godthab"_ba;
|
||||
QTest::newRow("Indiana/Indianapolis")
|
||||
<< "America/Indiana/Indianapolis"_ba << "America/Indianapolis"_ba;
|
||||
QTest::newRow("Kentucky/Louisville")
|
||||
<< "America/Kentucky/Louisville"_ba << "America/Louisville"_ba;
|
||||
QTest::newRow("Calcutta=Kolkata") << "Asia/Kolkata"_ba << "Asia/Calcutta"_ba;
|
||||
QTest::newRow("Katmandu=Kathmandu") << "Asia/Kathmandu"_ba << "Asia/Katmandu"_ba;
|
||||
QTest::newRow("Rangoon=Yangon") << "Asia/Yangon"_ba << "Asia/Rangoon"_ba;
|
||||
QTest::newRow("Saigon=Ho_Chi_Minh") << "Asia/Ho_Chi_Minh"_ba << "Asia/Saigon"_ba;
|
||||
QTest::newRow("Faeroe=Faroe") << "Atlantic/Faroe"_ba << "Atlantic/Faeroe"_ba;
|
||||
QTest::newRow("Currie=Hobart") << "Australia/Hobart"_ba << "Australia/Currie"_ba;
|
||||
QTest::newRow("Kiev=Kyiv") << "Europe/Kyiv"_ba << "Europe/Kiev"_ba;
|
||||
QTest::newRow("Uzhgorod=Kyiv") << "Europe/Kyiv"_ba << "Europe/Uzhgorod"_ba;
|
||||
QTest::newRow("Zaporozhye=Kyiv") << "Europe/Kyiv"_ba << "Europe/Zaporozhye"_ba;
|
||||
QTest::newRow("Fiji=Fiji") << "Pacific/Fiji"_ba << "Pacific/Fiji"_ba;
|
||||
QTest::newRow("Enderbury=Enderbury") << "Pacific/Enderbury"_ba << "Pacific/Enderbury"_ba;
|
||||
}
|
||||
|
||||
void tst_QTimeZone::aliasMatches()
|
||||
{
|
||||
QFETCH(const QByteArray, iana);
|
||||
QFETCH(const QByteArray, alias);
|
||||
const QTimeZone zone(iana);
|
||||
const QTimeZone peer(alias);
|
||||
if (!zone.isValid())
|
||||
QSKIP("Backend doesn't support IANA ID");
|
||||
|
||||
auto report = qScopeGuard([zone, peer]() {
|
||||
const QByteArray zid = zone.id(), pid = peer.id();
|
||||
qDebug("Using %s and %s", zid.constData(), pid.constData());
|
||||
});
|
||||
QVERIFY2(peer.isValid(), "Construction should have fallen back on IANA ID");
|
||||
QVERIFY(zone.aliasMatches(zone.id()));
|
||||
QVERIFY(zone.aliasMatches(iana));
|
||||
QVERIFY(peer.aliasMatches(peer.id()));
|
||||
QVERIFY(peer.aliasMatches(alias));
|
||||
QEXPECT_FAIL("Currie=Hobart", "Needs update to CLDR v44.1", Abort);
|
||||
QEXPECT_FAIL("Uzhgorod=Kyiv", "Needs update to CLDR v44.1", Abort);
|
||||
QEXPECT_FAIL("Zaporozhye=Kyiv", "Needs update to CLDR v44.1", Abort);
|
||||
QVERIFY(zone.aliasMatches(peer.id()));
|
||||
QVERIFY(zone.aliasMatches(alias));
|
||||
QVERIFY(peer.aliasMatches(zone.id()));
|
||||
QVERIFY(peer.aliasMatches(iana));
|
||||
report.dismiss();
|
||||
}
|
||||
|
||||
void tst_QTimeZone::specificTransition_data()
|
||||
{
|
||||
QTest::addColumn<QByteArray>("zone");
|
||||
@ -924,7 +987,7 @@ void tst_QTimeZone::stressTest()
|
||||
for (const QByteArray &id : idList) {
|
||||
QTimeZone testZone = QTimeZone(id);
|
||||
QCOMPARE(testZone.isValid(), true);
|
||||
QCOMPARE(testZone.id(), id);
|
||||
QVERIFY2(testZone.aliasMatches(id), testZone.id() + " != " + id);
|
||||
QDateTime testDate = QDateTime(QDate(2015, 1, 1), QTime(0, 0), UTC);
|
||||
testZone.territory();
|
||||
testZone.comment();
|
||||
@ -1860,7 +1923,7 @@ void tst_QTimeZone::stdCompatibility()
|
||||
QByteArrayView zoneName = QByteArrayView(timeZone->name());
|
||||
QTimeZone tz = QTimeZone::fromStdTimeZonePtr(timeZone);
|
||||
if (tz.isValid())
|
||||
QCOMPARE(tz.id(), zoneName);
|
||||
QVERIFY2(tz.aliasMatches(zoneName), tz.id().constData());
|
||||
else
|
||||
QVERIFY(!QTimeZone::isTimeZoneIdAvailable(zoneName.toByteArray()));
|
||||
#else
|
||||
|
Loading…
x
Reference in New Issue
Block a user