File indexing completed on 2026-09-29 09:23:28
0001
0002
0003
0004
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
0040
0041
0042
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
0070 bool isShort() const { return s.mode; }
0071
0072
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
0091 static constexpr int MinUtcOffsetSecs = -16 * 3600;
0092
0093
0094 static constexpr int MaxUtcOffsetSecs = +16 * 3600;
0095
0096
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
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
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
0271 template <typename>
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