1// Copyright (C) 2022 The Qt Company Ltd.
2// Copyright (C) 2013 John Layt <jlayt@kde.org>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5
6#ifndef QTIMEZONEPRIVATE_P_H
7#define QTIMEZONEPRIVATE_P_H
8
9//
10// W A R N I N G
11// -------------
12//
13// This file is not part of the Qt API. It exists for the convenience
14// of internal files. This header file may change from version to version
15// without notice, or even be removed.
16//
17// We mean it.
18//
19
20#include "qlist.h"
21#include "qtimezone.h"
22#include "private/qlocale_p.h"
23#include "private/qdatetime_p.h"
24
25#if QT_CONFIG(icu)
26#include <unicode/ucal.h>
27#endif
28
29#ifdef Q_OS_DARWIN
30Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone);
31#endif // Q_OS_DARWIN
32
33#ifdef Q_OS_WIN
34#include <qt_windows.h>
35#endif // Q_OS_WIN
36
37#ifdef Q_OS_ANDROID
38#include <QJniObject>
39#endif
40
41QT_REQUIRE_CONFIG(timezone);
42QT_BEGIN_NAMESPACE
43
44class Q_AUTOTEST_EXPORT QTimeZonePrivate : public QSharedData
45{
46public:
47 // Version of QTimeZone::OffsetData struct using msecs for efficiency
48 struct Data {
49 QString abbreviation;
50 qint64 atMSecsSinceEpoch;
51 int offsetFromUtc;
52 int standardTimeOffset;
53 int daylightTimeOffset;
54 Data()
55 : atMSecsSinceEpoch(QTimeZonePrivate::invalidMSecs()),
56 offsetFromUtc(QTimeZonePrivate::invalidSeconds()),
57 standardTimeOffset(QTimeZonePrivate::invalidSeconds()),
58 daylightTimeOffset(QTimeZonePrivate::invalidSeconds())
59 {}
60 Data(const QString &name, qint64 when, int offset, int standard)
61 : abbreviation(name),
62 atMSecsSinceEpoch(when),
63 offsetFromUtc(offset),
64 standardTimeOffset(standard),
65 daylightTimeOffset(offset - standard)
66 {}
67 };
68 typedef QList<Data> DataList;
69
70 // Create null time zone
71 QTimeZonePrivate();
72 QTimeZonePrivate(const QTimeZonePrivate &other);
73 virtual ~QTimeZonePrivate();
74
75 virtual QTimeZonePrivate *clone() const;
76
77 bool operator==(const QTimeZonePrivate &other) const;
78 bool operator!=(const QTimeZonePrivate &other) const;
79
80 bool isValid() const;
81
82 QByteArray id() const;
83 virtual QLocale::Territory territory() const;
84 virtual QString comment() const;
85
86 virtual QString displayName(qint64 atMSecsSinceEpoch,
87 QTimeZone::NameType nameType,
88 const QLocale &locale) const;
89 virtual QString displayName(QTimeZone::TimeType timeType,
90 QTimeZone::NameType nameType,
91 const QLocale &locale) const;
92 virtual QString abbreviation(qint64 atMSecsSinceEpoch) const;
93
94 virtual int offsetFromUtc(qint64 atMSecsSinceEpoch) const;
95 virtual int standardTimeOffset(qint64 atMSecsSinceEpoch) const;
96 virtual int daylightTimeOffset(qint64 atMSecsSinceEpoch) const;
97
98 virtual bool hasDaylightTime() const;
99 virtual bool isDaylightTime(qint64 atMSecsSinceEpoch) const;
100
101 virtual Data data(qint64 forMSecsSinceEpoch) const;
102 virtual Data data(QTimeZone::TimeType timeType) const;
103 virtual bool isDataLocale(const QLocale &locale) const;
104 QDateTimePrivate::ZoneState stateAtZoneTime(qint64 forLocalMSecs,
105 QDateTimePrivate::TransitionOptions resolve) const;
106
107 virtual bool hasTransitions() const;
108 virtual Data nextTransition(qint64 afterMSecsSinceEpoch) const;
109 virtual Data previousTransition(qint64 beforeMSecsSinceEpoch) const;
110 DataList transitions(qint64 fromMSecsSinceEpoch, qint64 toMSecsSinceEpoch) const;
111
112 virtual QByteArray systemTimeZoneId() const;
113
114 virtual bool isTimeZoneIdAvailable(const QByteArray &ianaId) const;
115 virtual QList<QByteArray> availableTimeZoneIds() const;
116 virtual QList<QByteArray> availableTimeZoneIds(QLocale::Territory territory) const;
117 virtual QList<QByteArray> availableTimeZoneIds(int utcOffset) const;
118
119 virtual void serialize(QDataStream &ds) const;
120
121 // Static Utility Methods
122 [[nodiscard]] static constexpr qint64 maxMSecs()
123 { return (std::numeric_limits<qint64>::max)(); }
124 [[nodiscard]] static constexpr qint64 minMSecs()
125 { return (std::numeric_limits<qint64>::min)() + 1; }
126 [[nodiscard]] static constexpr qint64 invalidMSecs()
127 { return (std::numeric_limits<qint64>::min)(); }
128 [[nodiscard]] static constexpr int invalidSeconds()
129 { return (std::numeric_limits<int>::min)(); }
130 static QTimeZone::OffsetData invalidOffsetData();
131 static QTimeZone::OffsetData toOffsetData(const Data &data);
132 static bool isValidId(const QByteArray &ianaId);
133 static QString isoOffsetFormat(int offsetFromUtc,
134 QTimeZone::NameType mode = QTimeZone::OffsetName);
135
136 static QByteArray aliasToIana(QByteArrayView alias);
137 static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);
138 static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);
139 static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,
140 QLocale::Territory territory);
141 static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId);
142 static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId,
143 QLocale::Territory territory);
144
145 // returns "UTC" QString and QByteArray
146 [[nodiscard]] static inline QString utcQString()
147 {
148 return QStringLiteral("UTC");
149 }
150
151 [[nodiscard]] static inline QByteArray utcQByteArray()
152 {
153 return QByteArrayLiteral("UTC");
154 }
155
156protected:
157 // Zones CLDR data says match a condition.
158 // Use to filter what the backend has available.
159 QList<QByteArrayView> matchingTimeZoneIds(QLocale::Territory territory) const;
160 QList<QByteArrayView> matchingTimeZoneIds(int utcOffset) const;
161
162#if QT_CONFIG(timezone_locale)
163private:
164 // Defined in qtimezonelocale.cpp
165 QString localeName(qint64 atMSecsSinceEpoch, int offsetFromUtc,
166 QTimeZone::TimeType timeType,
167 QTimeZone::NameType nameType,
168 const QLocale &locale) const;
169#endif // L10n helpers.
170
171protected:
172 QByteArray m_id;
173};
174Q_DECLARE_TYPEINFO(QTimeZonePrivate::Data, Q_RELOCATABLE_TYPE);
175
176template<> QTimeZonePrivate *QSharedDataPointer<QTimeZonePrivate>::clone();
177
178class Q_AUTOTEST_EXPORT QUtcTimeZonePrivate final : public QTimeZonePrivate
179{
180public:
181 // Create default UTC time zone
182 QUtcTimeZonePrivate();
183 // Create named time zone
184 QUtcTimeZonePrivate(const QByteArray &utcId);
185 // Create offset from UTC
186 QUtcTimeZonePrivate(qint32 offsetSeconds);
187 // Create custom offset from UTC
188 QUtcTimeZonePrivate(const QByteArray &zoneId, int offsetSeconds, const QString &name,
189 const QString &abbreviation, QLocale::Territory territory,
190 const QString &comment);
191 QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other);
192 virtual ~QUtcTimeZonePrivate();
193
194 // Fall-back for UTC[+-]\d+(:\d+){,2} IDs.
195 static qint64 offsetFromUtcString(QByteArrayView id);
196
197 QUtcTimeZonePrivate *clone() const override;
198
199 Data data(qint64 forMSecsSinceEpoch) const override;
200 Data data(QTimeZone::TimeType timeType) const override;
201 bool isDataLocale(const QLocale &locale) const override;
202
203 QLocale::Territory territory() const override;
204 QString comment() const override;
205
206 QString displayName(qint64 atMSecsSinceEpoch,
207 QTimeZone::NameType nameType,
208 const QLocale &locale) const override;
209 QString displayName(QTimeZone::TimeType timeType,
210 QTimeZone::NameType nameType,
211 const QLocale &locale) const override;
212 QString abbreviation(qint64 atMSecsSinceEpoch) const override;
213
214 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
215 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
216
217 QByteArray systemTimeZoneId() const override;
218
219 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
220 QList<QByteArray> availableTimeZoneIds() const override;
221 QList<QByteArray> availableTimeZoneIds(QLocale::Territory country) const override;
222 QList<QByteArray> availableTimeZoneIds(int utcOffset) const override;
223
224 void serialize(QDataStream &ds) const override;
225
226private:
227 void init(const QByteArray &zoneId, int offsetSeconds, const QString &name,
228 const QString &abbreviation, QLocale::Territory territory,
229 const QString &comment);
230
231 QString m_name;
232 QString m_abbreviation;
233 QString m_comment;
234 QLocale::Territory m_territory;
235 int m_offsetFromUtc;
236};
237
238// TODO: shuffle (almost reverse) order of and rework #if-ery here to use #elif
239// and match the #if-ery in each of QTZ's newBackendTimeZone() cascades for
240// backend selection.
241#if QT_CONFIG(icu) && !defined(Q_OS_UNIX)
242class Q_AUTOTEST_EXPORT QIcuTimeZonePrivate final : public QTimeZonePrivate
243{
244public:
245 // Create default time zone
246 QIcuTimeZonePrivate();
247 // Create named time zone
248 QIcuTimeZonePrivate(const QByteArray &ianaId);
249 QIcuTimeZonePrivate(const QIcuTimeZonePrivate &other);
250 ~QIcuTimeZonePrivate();
251
252 QIcuTimeZonePrivate *clone() const override;
253
254 using QTimeZonePrivate::displayName;
255 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
256 const QLocale &locale) const override;
257
258 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
259 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
260 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
261
262 bool hasDaylightTime() const override;
263 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
264
265 using QTimeZonePrivate::data;
266 Data data(qint64 forMSecsSinceEpoch) const override;
267
268 bool hasTransitions() const override;
269 Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
270 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
271
272 QByteArray systemTimeZoneId() const override;
273
274 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
275 QList<QByteArray> availableTimeZoneIds() const override;
276 QList<QByteArray> availableTimeZoneIds(QLocale::Territory territory) const override;
277 QList<QByteArray> availableTimeZoneIds(int offsetFromUtc) const override;
278
279private:
280 void init(const QByteArray &ianaId);
281
282 UCalendar *m_ucal;
283};
284#endif // ICU not on Unix.
285
286#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID)
287struct QTzTransitionTime
288{
289 qint64 atMSecsSinceEpoch;
290 quint8 ruleIndex;
291};
292Q_DECLARE_TYPEINFO(QTzTransitionTime, Q_PRIMITIVE_TYPE);
293struct QTzTransitionRule
294{
295 int stdOffset = 0;
296 int dstOffset = 0;
297 quint8 abbreviationIndex = 0;
298};
299Q_DECLARE_TYPEINFO(QTzTransitionRule, Q_PRIMITIVE_TYPE);
300constexpr inline bool operator==(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
301{ return lhs.stdOffset == rhs.stdOffset && lhs.dstOffset == rhs.dstOffset && lhs.abbreviationIndex == rhs.abbreviationIndex; }
302constexpr inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
303{ return !operator==(lhs, rhs); }
304
305// These are stored separately from QTzTimeZonePrivate so that they can be
306// cached, avoiding the need to re-parse them from disk constantly.
307struct QTzTimeZoneCacheEntry
308{
309 QList<QTzTransitionTime> m_tranTimes;
310 QList<QTzTransitionRule> m_tranRules;
311 QList<QByteArray> m_abbreviations;
312 QByteArray m_posixRule;
313 QTzTransitionRule m_preZoneRule;
314 bool m_hasDst = false;
315};
316
317class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate
318{
319 QTzTimeZonePrivate(const QTzTimeZonePrivate &) = default;
320public:
321 // Create default time zone
322 QTzTimeZonePrivate();
323 // Create named time zone
324 QTzTimeZonePrivate(const QByteArray &ianaId);
325 ~QTzTimeZonePrivate();
326
327 QTzTimeZonePrivate *clone() const override;
328
329 QLocale::Territory territory() const override;
330 QString comment() const override;
331
332 using QTimeZonePrivate::displayName;
333 QString displayName(QTimeZone::TimeType timeType,
334 QTimeZone::NameType nameType,
335 const QLocale &locale) const override;
336 QString abbreviation(qint64 atMSecsSinceEpoch) const override;
337
338 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
339 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
340 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
341
342 bool hasDaylightTime() const override;
343 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
344
345 Data data(qint64 forMSecsSinceEpoch) const override;
346 Data data(QTimeZone::TimeType timeType) const override;
347 bool isDataLocale(const QLocale &locale) const override;
348
349 bool hasTransitions() const override;
350 Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
351 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
352
353 QByteArray systemTimeZoneId() const override;
354
355 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
356 QList<QByteArray> availableTimeZoneIds() const override;
357 QList<QByteArray> availableTimeZoneIds(QLocale::Territory territory) const override;
358
359private:
360 static QByteArray staticSystemTimeZoneId();
361 QList<QTimeZonePrivate::Data> getPosixTransitions(qint64 msNear) const;
362
363 Data dataForTzTransition(QTzTransitionTime tran) const;
364 Data dataFromRule(QTzTransitionRule rule, qint64 msecsSinceEpoch) const;
365 QTzTimeZoneCacheEntry cached_data;
366 const QList<QTzTransitionTime> &tranCache() const { return cached_data.m_tranTimes; }
367};
368#endif // Q_OS_UNIX
369
370#ifdef Q_OS_DARWIN
371class Q_AUTOTEST_EXPORT QMacTimeZonePrivate final : public QTimeZonePrivate
372{
373public:
374 // Create default time zone
375 QMacTimeZonePrivate();
376 // Create named time zone
377 QMacTimeZonePrivate(const QByteArray &ianaId);
378 QMacTimeZonePrivate(const QMacTimeZonePrivate &other);
379 ~QMacTimeZonePrivate();
380
381 QMacTimeZonePrivate *clone() const override;
382
383 QString comment() const override;
384
385 using QTimeZonePrivate::displayName;
386 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
387 const QLocale &locale) const override;
388 QString abbreviation(qint64 atMSecsSinceEpoch) const override;
389
390 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
391 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
392 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
393
394 bool hasDaylightTime() const override;
395 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
396
397 using QTimeZonePrivate::data;
398 Data data(qint64 forMSecsSinceEpoch) const override;
399
400 bool hasTransitions() const override;
401 Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
402 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
403
404 QByteArray systemTimeZoneId() const override;
405 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
406 QList<QByteArray> availableTimeZoneIds() const override;
407
408 NSTimeZone *nsTimeZone() const;
409
410private:
411 void init(const QByteArray &zoneId);
412
413 NSTimeZone *m_nstz;
414};
415#endif // Q_OS_DARWIN
416
417#if defined(Q_OS_WIN) && !QT_CONFIG(icu)
418class Q_AUTOTEST_EXPORT QWinTimeZonePrivate final : public QTimeZonePrivate
419{
420public:
421 struct QWinTransitionRule {
422 int startYear;
423 int standardTimeBias;
424 int daylightTimeBias;
425 SYSTEMTIME standardTimeRule;
426 SYSTEMTIME daylightTimeRule;
427 };
428
429 // Create default time zone
430 QWinTimeZonePrivate();
431 // Create named time zone
432 QWinTimeZonePrivate(const QByteArray &ianaId);
433 QWinTimeZonePrivate(const QWinTimeZonePrivate &other);
434 ~QWinTimeZonePrivate();
435
436 QWinTimeZonePrivate *clone() const override;
437
438 QString comment() const override;
439
440 using QTimeZonePrivate::displayName;
441 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
442 const QLocale &locale) const override;
443 QString abbreviation(qint64 atMSecsSinceEpoch) const override;
444
445 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
446 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
447 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
448
449 bool hasDaylightTime() const override;
450 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
451
452 using QTimeZonePrivate::data;
453 Data data(qint64 forMSecsSinceEpoch) const override;
454
455 bool hasTransitions() const override;
456 Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
457 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
458
459 QByteArray systemTimeZoneId() const override;
460
461 QList<QByteArray> availableTimeZoneIds() const override;
462
463 // For use within implementation's TransitionTimePair:
464 QTimeZonePrivate::Data ruleToData(const QWinTransitionRule &rule, qint64 atMSecsSinceEpoch,
465 QTimeZone::TimeType type, bool fakeDst = false) const;
466private:
467 void init(const QByteArray &ianaId);
468
469 QByteArray m_windowsId;
470 QString m_displayName;
471 QString m_standardName;
472 QString m_daylightName;
473 QList<QWinTransitionRule> m_tranRules;
474};
475#endif // Q_OS_WIN && !icu
476
477#ifdef Q_OS_ANDROID
478class QAndroidTimeZonePrivate final : public QTimeZonePrivate
479{
480public:
481 // Create default time zone
482 QAndroidTimeZonePrivate();
483 // Create named time zone
484 QAndroidTimeZonePrivate(const QByteArray &ianaId);
485 QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &other);
486 ~QAndroidTimeZonePrivate();
487
488 QAndroidTimeZonePrivate *clone() const override;
489
490 using QTimeZonePrivate::displayName;
491 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
492 const QLocale &locale) const override;
493 QString abbreviation(qint64 atMSecsSinceEpoch) const override;
494
495 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
496 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
497 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
498
499 bool hasDaylightTime() const override;
500 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
501
502 using QTimeZonePrivate::data;
503 Data data(qint64 forMSecsSinceEpoch) const override;
504
505 QByteArray systemTimeZoneId() const override;
506 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
507 QList<QByteArray> availableTimeZoneIds() const override;
508
509private:
510 void init(const QByteArray &zoneId);
511
512 QJniObject androidTimeZone;
513
514};
515#endif // Q_OS_ANDROID
516
517QT_END_NAMESPACE
518
519#endif // QTIMEZONEPRIVATE_P_H
520

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtbase/src/corelib/time/qtimezoneprivate_p.h