QTimeZone: add construction from std::chrono::time_zone*

A time_zone represents a timezone identified by its IANA ID. This
allows for a straightforward conversion to QTimeZone.

[ChangeLog][QtCore][QTimeZone] QTimeZone can now be constructed
from a std::chrono::time_zone pointer.

Change-Id: I093d9fc2e989475d30730a9dcdef491903a2aeb2
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Giuseppe D'Angelo 2022-04-02 02:20:52 +02:00
parent 21ceefacdf
commit 69555b364d
3 changed files with 70 additions and 0 deletions

View File

@ -974,6 +974,15 @@ QList<QByteArray> QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId, QLo
return QTimeZonePrivate::windowsIdToIanaIds(windowsId, territory);
}
/*!
\fn QTimeZone QTimeZone::fromStdTimeZonePtr(const std::chrono::time_zone *timeZone)
\since 6.4
Returns a QTimeZone object representing the same time zone as \a timeZone.
The IANA ID of \a timeZone must be one of the available system IDs,
otherwise an invalid time zone will be returned.
*/
#ifndef QT_NO_DATASTREAM
// Invalid, as an IANA ID: too long, starts with - and has other invalid characters in it
static inline QString invalidId() { return QStringLiteral("-No Time Zone Specified!"); }

View File

@ -45,6 +45,8 @@
#include <QtCore/qlocale.h>
#include <QtCore/qdatetime.h>
#include <chrono>
QT_REQUIRE_CONFIG(timezone);
#if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE)
@ -164,6 +166,17 @@ public:
NSTimeZone *toNSTimeZone() const Q_DECL_NS_RETURNS_AUTORELEASED;
#endif
#if __cpp_lib_chrono >= 201907L || defined(Q_QDOC)
QT_POST_CXX17_API_IN_EXPORTED_CLASS
static QTimeZone fromStdTimeZonePtr(const std::chrono::time_zone *timeZone)
{
if (!timeZone)
return QTimeZone();
const std::string_view timeZoneName = timeZone->name();
return QTimeZone(QByteArrayView(timeZoneName).toByteArray());
}
#endif
private:
QTimeZone(QTimeZonePrivate &dd);
#ifndef QT_NO_DATASTREAM

View File

@ -77,6 +77,8 @@ private Q_SLOTS:
void winTest();
void localeSpecificDisplayName_data();
void localeSpecificDisplayName();
void stdCompatibility_data();
void stdCompatibility();
private:
void printTimeZone(const QTimeZone &tz);
@ -341,6 +343,11 @@ void tst_QTimeZone::systemZone()
};
for (const auto &date : dates)
QCOMPARE(date.startOfDay(Qt::LocalTime), date.startOfDay(zone));
#if __cpp_lib_chrono >= 201907L
const std::chrono::time_zone *currentTimeZone = std::chrono::current_zone();
QCOMPARE(QByteArrayView(currentTimeZone->name()), QByteArrayView(zone.id()));
#endif
}
void tst_QTimeZone::dataStreamTest()
@ -1609,5 +1616,46 @@ void tst_QTimeZone::testEpochTranPrivate(const QTimeZonePrivate &tzp)
}
#endif // QT_BUILD_INTERNAL
#if __cpp_lib_chrono >= 201907L
Q_DECLARE_METATYPE(const std::chrono::time_zone *);
#endif
void tst_QTimeZone::stdCompatibility_data()
{
#if __cpp_lib_chrono >= 201907L
QTest::addColumn<const std::chrono::time_zone *>("timeZone");
const std::chrono::tzdb &tzdb = std::chrono::get_tzdb();
qDebug() << "Using tzdb version:" << QByteArrayView(tzdb.version);
for (const std::chrono::time_zone &zone : tzdb.zones)
QTest::addRow(zone.name().data()) << &zone;
#else
QSKIP("This test requires C++20's <chrono>.");
#endif
}
void tst_QTimeZone::stdCompatibility()
{
#if __cpp_lib_chrono >= 201907L
QFETCH(const std::chrono::time_zone *, timeZone);
QByteArrayView zoneName = QByteArrayView(timeZone->name());
QTimeZone tz = QTimeZone::fromStdTimeZonePtr(timeZone);
if (tz.isValid()) {
QCOMPARE(tz.id(), zoneName);
} else {
// QTBUG-102187: a few timezones reported by tzdb might not be
// recognized by QTimeZone. This happens for instance on Windows, where
// tzdb is using ICU, whose database does not match QTimeZone's.
const bool isKnownUnknown =
!zoneName.contains('/')
|| zoneName == "Antarctica/Troll"
|| zoneName.startsWith("SystemV/");
QVERIFY(isKnownUnknown);
}
#else
QSKIP("This test requires C++20's <chrono>.");
#endif
}
QTEST_APPLESS_MAIN(tst_QTimeZone)
#include "tst_qtimezone.moc"