Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-29 09:23:28

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