Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:40

0001 // Copyright (C) 2017 The Qt Company Ltd.
0002 // Copyright (C) 2013 John Layt <jlayt@kde.org>
0003 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0004 
0005 #ifndef QTIMEZONE_H
0006 #define QTIMEZONE_H
0007 
0008 #include <QtCore/qcompare.h>
0009 #include <QtCore/qdatetime.h>
0010 #include <QtCore/qlocale.h>
0011 #include <QtCore/qswap.h>
0012 #include <QtCore/qtclasshelpermacros.h>
0013 
0014 #include <chrono>
0015 
0016 #if QT_CONFIG(timezone) && (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE)
0017 Q_FORWARD_DECLARE_CF_TYPE(CFTimeZone);
0018 Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone);
0019 #endif
0020 
0021 QT_BEGIN_NAMESPACE
0022 
0023 class QTimeZonePrivate;
0024 
0025 class Q_CORE_EXPORT QTimeZone
0026 {
0027     struct ShortData
0028     {
0029 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
0030         quintptr mode : 2;
0031 #endif
0032         qintptr offset : sizeof(void *) * 8 - 2;
0033 
0034 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
0035         quintptr mode : 2;
0036 #endif
0037 
0038         // mode is a cycled Qt::TimeSpec, (int(spec) + 1) % 4, so that zero
0039         // (lowest bits of a pointer) matches spec being Qt::TimeZone, for which
0040         // Data holds a QTZP pointer instead of ShortData.
0041         // Passing Qt::TimeZone gets the equivalent of a null QTZP; it is not short.
0042         constexpr ShortData(Qt::TimeSpec spec, int secondsAhead = 0)
0043 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
0044             : offset(spec == Qt::OffsetFromUTC ? secondsAhead : 0),
0045               mode((int(spec) + 1) & 3)
0046 #else
0047             : mode((int(spec) + 1) & 3),
0048               offset(spec == Qt::OffsetFromUTC ? secondsAhead : 0)
0049 #endif
0050         {
0051         }
0052         friend constexpr bool operator==(const ShortData &lhs, const ShortData &rhs)
0053         { return lhs.mode == rhs.mode && lhs.offset == rhs.offset; }
0054         constexpr Qt::TimeSpec spec() const { return Qt::TimeSpec((mode + 3) & 3); }
0055     };
0056 
0057     union Data
0058     {
0059         Data() noexcept;
0060         Data(ShortData sd) : s(sd) {}
0061         Data(const Data &other) noexcept;
0062         Data(Data &&other) noexcept : d(std::exchange(other.d, nullptr)) {}
0063         Data &operator=(const Data &other) noexcept;
0064         Data &operator=(Data &&other) noexcept { swap(other); return *this; }
0065         ~Data();
0066 
0067         void swap(Data &other) noexcept { qt_ptr_swap(d, other.d); }
0068         // isShort() is equivalent to s.spec() != Qt::TimeZone
0069         bool isShort() const { return s.mode; } // a.k.a. quintptr(d) & 3
0070 
0071         // Typse must support: out << wrap("C-strings");
0072         template <typename Stream, typename Wrap>
0073         void serialize(Stream &out, const Wrap &wrap) const;
0074 
0075         Data(QTimeZonePrivate *dptr) noexcept;
0076         Data &operator=(QTimeZonePrivate *dptr) noexcept;
0077         const QTimeZonePrivate *operator->() const { Q_ASSERT(!isShort()); return d; }
0078         QTimeZonePrivate *operator->() { Q_ASSERT(!isShort()); return d; }
0079 
0080         QTimeZonePrivate *d = nullptr;
0081         ShortData s;
0082     };
0083     QTimeZone(ShortData sd) : d(sd) {}
0084 
0085 public:
0086     // Sane UTC offsets range from -16 to +16 hours:
0087     static constexpr int MinUtcOffsetSecs = -16 * 3600;
0088     // No known modern zone > 12 hrs West of Greenwich.
0089     // Until 1844, Asia/Manila (in The Philippines) was at 15:56 West.
0090     static constexpr int MaxUtcOffsetSecs = +16 * 3600;
0091     // No known modern zone > 14 hrs East of Greenwich.
0092     // Until 1867, America/Metlakatla (in Alaska) was at 15:13:42 East.
0093 
0094     enum Initialization { LocalTime, UTC };
0095 
0096     QTimeZone() noexcept;
0097     Q_IMPLICIT QTimeZone(Initialization spec) noexcept
0098         : d(ShortData(spec == UTC ? Qt::UTC : Qt::LocalTime)) {}
0099 
0100 #if QT_CONFIG(timezone)
0101     explicit QTimeZone(int offsetSeconds);
0102     explicit QTimeZone(const QByteArray &ianaId);
0103     QTimeZone(const QByteArray &zoneId, int offsetSeconds, const QString &name,
0104               const QString &abbreviation, QLocale::Territory territory = QLocale::AnyTerritory,
0105               const QString &comment = QString());
0106 #endif // timezone backends
0107 
0108     QTimeZone(const QTimeZone &other) noexcept;
0109     QTimeZone(QTimeZone &&other) noexcept : d(std::move(other.d)) {}
0110     ~QTimeZone();
0111 
0112     QTimeZone &operator=(const QTimeZone &other);
0113     QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QTimeZone)
0114 
0115     void swap(QTimeZone &other) noexcept
0116     { d.swap(other.d); }
0117 
0118 #if QT_CORE_REMOVED_SINCE(6, 7)
0119     bool operator==(const QTimeZone &other) const;
0120     bool operator!=(const QTimeZone &other) const;
0121 #endif
0122 
0123     bool isValid() const;
0124 
0125     static QTimeZone fromDurationAheadOfUtc(std::chrono::seconds offset)
0126     {
0127         return QTimeZone((offset.count() >= MinUtcOffsetSecs && offset.count() <= MaxUtcOffsetSecs)
0128                          ? ShortData(offset.count() ? Qt::OffsetFromUTC : Qt::UTC,
0129                                      int(offset.count()))
0130                          : ShortData(Qt::TimeZone));
0131     }
0132     static QTimeZone fromSecondsAheadOfUtc(int offset)
0133     {
0134         return fromDurationAheadOfUtc(std::chrono::seconds{offset});;
0135     }
0136     constexpr Qt::TimeSpec timeSpec() const noexcept { return d.s.spec(); }
0137     constexpr int fixedSecondsAheadOfUtc() const noexcept
0138     { return timeSpec() == Qt::OffsetFromUTC ? int(d.s.offset) : 0; }
0139 
0140     static constexpr bool isUtcOrFixedOffset(Qt::TimeSpec spec) noexcept
0141     { return spec == Qt::UTC || spec == Qt::OffsetFromUTC; }
0142     constexpr bool isUtcOrFixedOffset() const noexcept { return isUtcOrFixedOffset(timeSpec()); }
0143 
0144 #if QT_CONFIG(timezone)
0145     QTimeZone asBackendZone() const;
0146 
0147     enum TimeType {
0148         StandardTime = 0,
0149         DaylightTime = 1,
0150         GenericTime = 2
0151     };
0152 
0153     enum NameType {
0154         DefaultName = 0,
0155         LongName = 1,
0156         ShortName = 2,
0157         OffsetName = 3
0158     };
0159 
0160     struct OffsetData {
0161         QString abbreviation;
0162         QDateTime atUtc;
0163         int offsetFromUtc;
0164         int standardTimeOffset;
0165         int daylightTimeOffset;
0166     };
0167     typedef QList<OffsetData> OffsetDataList;
0168 
0169     QByteArray id() const;
0170     QLocale::Territory territory() const;
0171 #  if QT_DEPRECATED_SINCE(6, 6)
0172     QT_DEPRECATED_VERSION_X_6_6("Use territory() instead")
0173     QLocale::Country country() const;
0174 #  endif
0175     QString comment() const;
0176 
0177     QString displayName(const QDateTime &atDateTime,
0178                         QTimeZone::NameType nameType = QTimeZone::DefaultName,
0179                         const QLocale &locale = QLocale()) const;
0180     QString displayName(QTimeZone::TimeType timeType,
0181                         QTimeZone::NameType nameType = QTimeZone::DefaultName,
0182                         const QLocale &locale = QLocale()) const;
0183     QString abbreviation(const QDateTime &atDateTime) const;
0184 
0185     int offsetFromUtc(const QDateTime &atDateTime) const;
0186     int standardTimeOffset(const QDateTime &atDateTime) const;
0187     int daylightTimeOffset(const QDateTime &atDateTime) const;
0188 
0189     bool hasDaylightTime() const;
0190     bool isDaylightTime(const QDateTime &atDateTime) const;
0191 
0192     OffsetData offsetData(const QDateTime &forDateTime) const;
0193 
0194     bool hasTransitions() const;
0195     OffsetData nextTransition(const QDateTime &afterDateTime) const;
0196     OffsetData previousTransition(const QDateTime &beforeDateTime) const;
0197     OffsetDataList transitions(const QDateTime &fromDateTime, const QDateTime &toDateTime) const;
0198 
0199     static QByteArray systemTimeZoneId();
0200     static QTimeZone systemTimeZone();
0201     static QTimeZone utc();
0202 
0203     static bool isTimeZoneIdAvailable(const QByteArray &ianaId);
0204 
0205     static QList<QByteArray> availableTimeZoneIds();
0206     static QList<QByteArray> availableTimeZoneIds(QLocale::Territory territory);
0207     static QList<QByteArray> availableTimeZoneIds(int offsetSeconds);
0208 
0209     static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);
0210     static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);
0211     static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,
0212                                                QLocale::Territory territory);
0213     static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId);
0214     static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId,
0215                                                 QLocale::Territory territory);
0216 
0217 #  if (defined(Q_OS_DARWIN) || defined(Q_QDOC)) && !defined(QT_NO_SYSTEMLOCALE)
0218     static QTimeZone fromCFTimeZone(CFTimeZoneRef timeZone);
0219     CFTimeZoneRef toCFTimeZone() const Q_DECL_CF_RETURNS_RETAINED;
0220     static QTimeZone fromNSTimeZone(const NSTimeZone *timeZone);
0221     NSTimeZone *toNSTimeZone() const Q_DECL_NS_RETURNS_AUTORELEASED;
0222 #  endif
0223 
0224 #  if __cpp_lib_chrono >= 201907L || defined(Q_QDOC)
0225     QT_POST_CXX17_API_IN_EXPORTED_CLASS
0226     static QTimeZone fromStdTimeZonePtr(const std::chrono::time_zone *timeZone)
0227     {
0228         if (!timeZone)
0229             return QTimeZone();
0230         const std::string_view timeZoneName = timeZone->name();
0231         return QTimeZone(QByteArrayView(timeZoneName).toByteArray());
0232     }
0233 #  endif
0234 #endif // feature timezone
0235 private:
0236     friend Q_CORE_EXPORT bool comparesEqual(const QTimeZone &lhs, const QTimeZone &rhs) noexcept;
0237     Q_DECLARE_EQUALITY_COMPARABLE(QTimeZone)
0238 
0239 #ifndef QT_NO_DATASTREAM
0240     friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz);
0241 #endif
0242 #ifndef QT_NO_DEBUG_STREAM
0243     friend Q_CORE_EXPORT QDebug operator<<(QDebug dbg, const QTimeZone &tz);
0244 #endif
0245     QTimeZone(QTimeZonePrivate &dd);
0246     friend class QTimeZonePrivate;
0247     friend class QDateTime;
0248     friend class QDateTimePrivate;
0249     Data d;
0250 };
0251 
0252 #if QT_CONFIG(timezone)
0253 Q_DECLARE_TYPEINFO(QTimeZone::OffsetData, Q_RELOCATABLE_TYPE);
0254 #endif
0255 Q_DECLARE_SHARED(QTimeZone)
0256 
0257 #ifndef QT_NO_DATASTREAM
0258 Q_CORE_EXPORT QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz);
0259 Q_CORE_EXPORT QDataStream &operator>>(QDataStream &ds, QTimeZone &tz);
0260 #endif
0261 
0262 #ifndef QT_NO_DEBUG_STREAM
0263 Q_CORE_EXPORT QDebug operator<<(QDebug dbg, const QTimeZone &tz);
0264 #endif
0265 
0266 #if QT_CONFIG(timezone) && __cpp_lib_chrono >= 201907L
0267 // zoned_time
0268 template <typename> // QT_POST_CXX17_API_IN_EXPORTED_CLASS
0269 inline QDateTime QDateTime::fromStdZonedTime(const std::chrono::zoned_time<
0270                                                 std::chrono::milliseconds,
0271                                                 const std::chrono::time_zone *
0272                                              > &time)
0273 {
0274     const auto sysTime = time.get_sys_time();
0275     const QTimeZone timeZone = QTimeZone::fromStdTimeZonePtr(time.get_time_zone());
0276     return fromMSecsSinceEpoch(sysTime.time_since_epoch().count(), timeZone);
0277 }
0278 #endif
0279 
0280 QT_END_NAMESPACE
0281 
0282 #endif // QTIMEZONE_H