123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 | // Copyright (C) 2017 The Qt Company Ltd.// Copyright (C) 2013 John Layt <jlayt@kde.org>// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only#ifndef QTIMEZONE_H#define QTIMEZONE_H#include <QtCore/qcompare.h>#include <QtCore/qdatetime.h>#include <QtCore/qlocale.h>#include <QtCore/qswap.h>#include <QtCore/qtclasshelpermacros.h>#include <chrono>#if QT_CONFIG(timezone) && (defined(Q_OS_DARWIN) || defined(Q_QDOC))Q_FORWARD_DECLARE_CF_TYPE(CFTimeZone);Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone);#endif QT_BEGIN_NAMESPACE class QTimeZonePrivate;class Q_CORE_EXPORT QTimeZone {struct ShortData {#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN quintptr mode :2;#endif qintptr offset :sizeof(void*) *8-2;#if Q_BYTE_ORDER == Q_BIG_ENDIAN quintptr mode :2;#endif// mode is a cycled Qt::TimeSpec, (int(spec) + 1) % 4, so that zero// (lowest bits of a pointer) matches spec being Qt::TimeZone, for which// Data holds a QTZP pointer instead of ShortData.// Passing Qt::TimeZone gets the equivalent of a null QTZP; it is not short.constexprShortData(Qt::TimeSpec spec,int secondsAhead =0)#if Q_BYTE_ORDER == Q_BIG_ENDIAN:offset(spec ==Qt::OffsetFromUTC ? secondsAhead :0),mode((int(spec) +1) &3)#else:mode((int(spec) +1) &3),offset(spec ==Qt::OffsetFromUTC ? secondsAhead :0)#endif{}friend constexprbooloperator==(ShortData lhs, ShortData rhs){return lhs.mode == rhs.mode && lhs.offset == rhs.offset; }constexpr Qt::TimeSpec spec()const{returnQt::TimeSpec((mode +3) &3); }};union Data {Data() noexcept;Data(ShortData sd) :s(sd) {}Data(const Data &other) noexcept;Data(Data &&other) noexcept :d(std::exchange(other.d,nullptr)) {} Data &operator=(const Data &other) noexcept; Data &operator=(Data &&other) noexcept {swap(other);return*this; }~Data();voidswap(Data &other) noexcept {qt_ptr_swap(d, other.d); }// isShort() is equivalent to s.spec() != Qt::TimeZoneboolisShort()const{return s.mode; }// a.k.a. quintptr(d) & 3// Typse must support: out << wrap("C-strings");template<typename Stream, typename Wrap>voidserialize(Stream &out,const Wrap &wrap)const;Data(QTimeZonePrivate *dptr) noexcept; Data &operator=(QTimeZonePrivate *dptr) noexcept;const QTimeZonePrivate *operator->()const{Q_ASSERT(!isShort());return d; } QTimeZonePrivate *operator->() {Q_ASSERT(!isShort());return d; } QTimeZonePrivate *d =nullptr; ShortData s;};QTimeZone(ShortData sd) :d(sd) {}public:// Sane UTC offsets range from -16 to +16 hours:staticconstexprint MinUtcOffsetSecs = -16*3600;// No known modern zone > 12 hrs West of Greenwich.// Until 1844, Asia/Manila (in The Philippines) was at 15:56 West.staticconstexprint MaxUtcOffsetSecs = +16*3600;// No known modern zone > 14 hrs East of Greenwich.// Until 1867, America/Metlakatla (in Alaska) was at 15:13:42 East.enum Initialization { LocalTime, UTC };QTimeZone() noexcept; Q_IMPLICIT QTimeZone(Initialization spec) noexcept :d(ShortData(spec == UTC ?Qt::UTC :Qt::LocalTime)) {}#if QT_CONFIG(timezone)explicitQTimeZone(int offsetSeconds);explicitQTimeZone(const QByteArray &ianaId);QTimeZone(const QByteArray &zoneId,int offsetSeconds,const QString &name,const QString &abbreviation,QLocale::Territory territory =QLocale::AnyTerritory,const QString &comment =QString());#endif// timezone backendsQTimeZone(const QTimeZone &other) noexcept;QTimeZone(QTimeZone &&other) noexcept :d(std::move(other.d)) {}~QTimeZone(); QTimeZone &operator=(const QTimeZone &other);QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QTimeZone)voidswap(QTimeZone &other) noexcept { d.swap(other.d); }#if QT_CORE_REMOVED_SINCE(6, 7)booloperator==(const QTimeZone &other)const;booloperator!=(const QTimeZone &other)const;#endifboolisValid()const;static QTimeZone fromDurationAheadOfUtc(std::chrono::seconds offset){returnQTimeZone((offset.count() >= MinUtcOffsetSecs && offset.count() <= MaxUtcOffsetSecs)?ShortData(offset.count() ?Qt::OffsetFromUTC :Qt::UTC,int(offset.count())):ShortData(Qt::TimeZone));}static QTimeZone fromSecondsAheadOfUtc(int offset){returnfromDurationAheadOfUtc(std::chrono::seconds{offset});}constexpr Qt::TimeSpec timeSpec()const noexcept {return d.s.spec(); }constexprintfixedSecondsAheadOfUtc()const noexcept {returntimeSpec() ==Qt::OffsetFromUTC ?int(d.s.offset) :0; }staticconstexprboolisUtcOrFixedOffset(Qt::TimeSpec spec) noexcept {return spec ==Qt::UTC || spec ==Qt::OffsetFromUTC; }constexprboolisUtcOrFixedOffset()const noexcept {returnisUtcOrFixedOffset(timeSpec()); }#if QT_CONFIG(timezone) QTimeZone asBackendZone()const;enum TimeType { StandardTime =0, DaylightTime =1, GenericTime =2};enum NameType { DefaultName =0, LongName =1, ShortName =2, OffsetName =3};struct OffsetData { QString abbreviation; QDateTime atUtc;int offsetFromUtc;int standardTimeOffset;int daylightTimeOffset;};typedef QList<OffsetData> OffsetDataList;boolhasAlternativeName(QByteArrayView alias)const; QByteArray id()const;QLocale::Territory territory()const;# if QT_DEPRECATED_SINCE(6, 6)QT_DEPRECATED_VERSION_X_6_6("Use territory() instead")QLocale::Country country()const;# endif QString comment()const; QString displayName(const QDateTime &atDateTime, NameType nameType = DefaultName,const QLocale &locale =QLocale())const; QString displayName(TimeType timeType, NameType nameType = DefaultName,const QLocale &locale =QLocale())const; QString abbreviation(const QDateTime &atDateTime)const;intoffsetFromUtc(const QDateTime &atDateTime)const;intstandardTimeOffset(const QDateTime &atDateTime)const;intdaylightTimeOffset(const QDateTime &atDateTime)const;boolhasDaylightTime()const;boolisDaylightTime(const QDateTime &atDateTime)const; OffsetData offsetData(const QDateTime &forDateTime)const;boolhasTransitions()const; OffsetData nextTransition(const QDateTime &afterDateTime)const; OffsetData previousTransition(const QDateTime &beforeDateTime)const; OffsetDataList transitions(const QDateTime &fromDateTime,const QDateTime &toDateTime)const;static QByteArray systemTimeZoneId();static QTimeZone systemTimeZone();static QTimeZone utc();static boolisTimeZoneIdAvailable(const QByteArray &ianaId);static QList<QByteArray>availableTimeZoneIds();static QList<QByteArray>availableTimeZoneIds(QLocale::Territory territory);static QList<QByteArray>availableTimeZoneIds(int offsetSeconds);static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,QLocale::Territory territory);static QList<QByteArray>windowsIdToIanaIds(const QByteArray &windowsId);static QList<QByteArray>windowsIdToIanaIds(const QByteArray &windowsId,QLocale::Territory territory);# if defined(Q_OS_DARWIN) || defined(Q_QDOC)static QTimeZone fromCFTimeZone(CFTimeZoneRef timeZone); CFTimeZoneRef toCFTimeZone()const Q_DECL_CF_RETURNS_RETAINED;static QTimeZone fromNSTimeZone(const NSTimeZone *timeZone); 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(conststd::chrono::time_zone *timeZone){if(!timeZone)returnQTimeZone();conststd::string_view timeZoneName = timeZone->name();returnQTimeZone(QByteArrayView(timeZoneName).toByteArray());}# endif#endif// feature timezoneprivate:friend Q_CORE_EXPORT boolcomparesEqual(const QTimeZone &lhs,const QTimeZone &rhs) noexcept;Q_DECLARE_EQUALITY_COMPARABLE(QTimeZone)#ifndef QT_NO_DATASTREAMfriend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds,const QTimeZone &tz);#endif#ifndef QT_NO_DEBUG_STREAMfriend Q_CORE_EXPORT QDebug operator<<(QDebug dbg,const QTimeZone &tz);#endifQTimeZone(QTimeZonePrivate &dd);friend class QTimeZonePrivate;friend class QDateTime;friend class QDateTimePrivate; Data d;};#if QT_CONFIG(timezone)Q_DECLARE_TYPEINFO(QTimeZone::OffsetData, Q_RELOCATABLE_TYPE);#endifQ_DECLARE_SHARED(QTimeZone)#ifndef QT_NO_DATASTREAM Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds,const QTimeZone &tz); Q_CORE_EXPORT QDataStream &operator>>(QDataStream &ds, QTimeZone &tz);#endif#ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug dbg,const QTimeZone &tz);#endif#if QT_CONFIG(timezone) && __cpp_lib_chrono >= 201907L// zoned_timetemplate<typename>// QT_POST_CXX17_API_IN_EXPORTED_CLASSinline QDateTime QDateTime::fromStdZonedTime(conststd::chrono::zoned_time<std::chrono::milliseconds,conststd::chrono::time_zone *> &time){constauto sysTime = time.get_sys_time();const QTimeZone timeZone =QTimeZone::fromStdTimeZonePtr(time.get_time_zone());returnfromMSecsSinceEpoch(sysTime.time_since_epoch().count(), timeZone);}#endif QT_END_NAMESPACE #endif// QTIMEZONE_H
|