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(timezone_tzdb)
26#include <chrono>
27#endif
28#include <optional>
29
30#if QT_CONFIG(icu)
31#include <unicode/ucal.h>
32#endif
33
34#ifdef Q_OS_DARWIN
35Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone);
36#endif // Q_OS_DARWIN
37
38#ifdef Q_OS_WIN
39#include <qt_windows.h>
40#endif // Q_OS_WIN
41
42#ifdef Q_OS_ANDROID
43#include <QJniObject>
44#endif
45
46QT_REQUIRE_CONFIG(timezone);
47QT_BEGIN_NAMESPACE
48
49class Q_AUTOTEST_EXPORT QTimeZonePrivate : public QSharedData
50{
51 // Nothing should be copy-assigning instances of either this or its derived
52 // classes (only clone() should copy, using the copy-constructor):
53 bool operator=(const QTimeZonePrivate &) const = delete;
54protected:
55 QTimeZonePrivate(const QTimeZonePrivate &other) = default;
56public:
57 // Version of QTimeZone::OffsetData struct using msecs for efficiency
58 struct Data {
59 QString abbreviation;
60 qint64 atMSecsSinceEpoch;
61 int offsetFromUtc;
62 int standardTimeOffset;
63 int daylightTimeOffset;
64 Data()
65 : atMSecsSinceEpoch(QTimeZonePrivate::invalidMSecs()),
66 offsetFromUtc(QTimeZonePrivate::invalidSeconds()),
67 standardTimeOffset(QTimeZonePrivate::invalidSeconds()),
68 daylightTimeOffset(QTimeZonePrivate::invalidSeconds())
69 {}
70 Data(const QString &name, qint64 when, int offset, int standard)
71 : abbreviation(name),
72 atMSecsSinceEpoch(when),
73 offsetFromUtc(offset),
74 standardTimeOffset(standard),
75 daylightTimeOffset(offset - standard)
76 {}
77 };
78 typedef QList<Data> DataList;
79
80 // Create null time zone
81 QTimeZonePrivate();
82 virtual ~QTimeZonePrivate();
83
84 virtual QTimeZonePrivate *clone() const = 0;
85
86 bool operator==(const QTimeZonePrivate &other) const;
87 bool operator!=(const QTimeZonePrivate &other) const;
88
89 bool isValid() const;
90
91 QByteArray id() const;
92 virtual QLocale::Territory territory() const;
93 virtual QString comment() const;
94
95 virtual QString displayName(qint64 atMSecsSinceEpoch,
96 QTimeZone::NameType nameType,
97 const QLocale &locale) const;
98 virtual QString displayName(QTimeZone::TimeType timeType,
99 QTimeZone::NameType nameType,
100 const QLocale &locale) const;
101 virtual QString abbreviation(qint64 atMSecsSinceEpoch) const;
102
103 virtual int offsetFromUtc(qint64 atMSecsSinceEpoch) const;
104 virtual int standardTimeOffset(qint64 atMSecsSinceEpoch) const;
105 virtual int daylightTimeOffset(qint64 atMSecsSinceEpoch) const;
106
107 virtual bool hasDaylightTime() const;
108 virtual bool isDaylightTime(qint64 atMSecsSinceEpoch) const;
109
110 virtual Data data(qint64 forMSecsSinceEpoch) const;
111 virtual Data data(QTimeZone::TimeType timeType) const;
112 virtual bool isDataLocale(const QLocale &locale) const;
113 static bool isAnglicLocale(const QLocale &locale)
114 {
115 // Sufficiently like the C locale for displayName()-related purposes:
116 const QLocale::Language lang = locale.language();
117 return lang == QLocale::C
118 || (lang == QLocale::English && locale.script() == QLocale::LatinScript);
119 }
120 QDateTimePrivate::ZoneState stateAtZoneTime(qint64 forLocalMSecs,
121 QDateTimePrivate::TransitionOptions resolve) const;
122
123 virtual bool hasTransitions() const;
124 virtual Data nextTransition(qint64 afterMSecsSinceEpoch) const;
125 virtual Data previousTransition(qint64 beforeMSecsSinceEpoch) const;
126 DataList transitions(qint64 fromMSecsSinceEpoch, qint64 toMSecsSinceEpoch) const;
127
128 virtual QByteArray systemTimeZoneId() const;
129
130 virtual bool isTimeZoneIdAvailable(const QByteArray &ianaId) const;
131 virtual QList<QByteArray> availableTimeZoneIds() const = 0;
132 virtual QList<QByteArray> availableTimeZoneIds(QLocale::Territory territory) const;
133 virtual QList<QByteArray> availableTimeZoneIds(int utcOffset) const;
134
135 virtual void serialize(QDataStream &ds) const;
136
137 // Static Utility Methods
138 [[nodiscard]] static constexpr qint64 maxMSecs()
139 { return (std::numeric_limits<qint64>::max)(); }
140 [[nodiscard]] static constexpr qint64 minMSecs()
141 { return (std::numeric_limits<qint64>::min)() + 1; }
142 [[nodiscard]] static constexpr qint64 invalidMSecs()
143 { return (std::numeric_limits<qint64>::min)(); }
144 [[nodiscard]] static constexpr int invalidSeconds()
145 { return (std::numeric_limits<int>::min)(); }
146 static QTimeZone::OffsetData invalidOffsetData();
147 static QTimeZone::OffsetData toOffsetData(const Data &data);
148 static bool isValidId(const QByteArray &ianaId);
149 static QString isoOffsetFormat(int offsetFromUtc,
150 QTimeZone::NameType mode = QTimeZone::OffsetName);
151
152 static QByteArray aliasToIana(QByteArrayView alias);
153 static QByteArray ianaIdToWindowsId(const QByteArray &ianaId);
154 static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId);
155 static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId,
156 QLocale::Territory territory);
157 static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId);
158 static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId,
159 QLocale::Territory territory);
160 struct NamePrefixMatch
161 {
162 QByteArray ianaId;
163 qsizetype nameLength = 0;
164 QTimeZone::TimeType timeType = QTimeZone::GenericTime;
165 };
166 static NamePrefixMatch findLongNamePrefix(QStringView text, const QLocale &locale,
167 std::optional<qint64> atEpochMillis = std::nullopt);
168
169 // returns "UTC" QString and QByteArray
170 [[nodiscard]] static inline QString utcQString()
171 {
172 return QStringLiteral("UTC");
173 }
174
175 [[nodiscard]] static inline QByteArray utcQByteArray()
176 {
177 return QByteArrayLiteral("UTC");
178 }
179
180 [[nodiscard]] static QTimeZone utcQTimeZone();
181
182#ifdef QT_BUILD_INTERNAL // For the benefit of a test
183 [[nodiscard]] static inline const QTimeZonePrivate *extractPrivate(const QTimeZone &zone)
184 {
185 return zone.d.operator->();
186 }
187#endif
188
189protected:
190 // Zones CLDR data says match a condition.
191 // Use to filter what the backend has available.
192 QList<QByteArrayView> matchingTimeZoneIds(QLocale::Territory territory) const;
193 QList<QByteArrayView> matchingTimeZoneIds(int utcOffset) const;
194
195#if QT_CONFIG(timezone_locale)
196 // Defined in qtimezonelocale.cpp
197 QString localeName(qint64 atMSecsSinceEpoch, int offsetFromUtc,
198 QTimeZone::TimeType timeType,
199 QTimeZone::NameType nameType,
200 const QLocale &locale) const;
201#endif // L10n helpers.
202
203 QByteArray m_id;
204};
205Q_DECLARE_TYPEINFO(QTimeZonePrivate::Data, Q_RELOCATABLE_TYPE);
206
207template<> QTimeZonePrivate *QSharedDataPointer<QTimeZonePrivate>::clone();
208
209class Q_AUTOTEST_EXPORT QUtcTimeZonePrivate final : public QTimeZonePrivate
210{
211 bool operator=(const QUtcTimeZonePrivate &) const = delete;
212 QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other);
213public:
214 // Create default UTC time zone
215 QUtcTimeZonePrivate();
216 // Create named time zone
217 QUtcTimeZonePrivate(const QByteArray &utcId);
218 // Create offset from UTC
219 QUtcTimeZonePrivate(qint32 offsetSeconds);
220 // Create custom offset from UTC
221 QUtcTimeZonePrivate(const QByteArray &zoneId, int offsetSeconds, const QString &name,
222 const QString &abbreviation, QLocale::Territory territory,
223 const QString &comment);
224 virtual ~QUtcTimeZonePrivate();
225
226 // Fall-back for UTC[+-]\d+(:\d+){,2} IDs.
227 static qint64 offsetFromUtcString(QByteArrayView id);
228
229 QUtcTimeZonePrivate *clone() const override;
230
231 Data data(qint64 forMSecsSinceEpoch) const override;
232 Data data(QTimeZone::TimeType timeType) const override;
233 bool isDataLocale(const QLocale &locale) const override;
234
235 QLocale::Territory territory() const override;
236 QString comment() const override;
237
238 QString displayName(qint64 atMSecsSinceEpoch,
239 QTimeZone::NameType nameType,
240 const QLocale &locale) const override;
241 QString displayName(QTimeZone::TimeType timeType,
242 QTimeZone::NameType nameType,
243 const QLocale &locale) const override;
244 QString abbreviation(qint64 atMSecsSinceEpoch) const override;
245
246 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
247 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
248
249 QByteArray systemTimeZoneId() const override;
250
251 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
252 QList<QByteArray> availableTimeZoneIds() const override;
253 QList<QByteArray> availableTimeZoneIds(QLocale::Territory country) const override;
254 QList<QByteArray> availableTimeZoneIds(int utcOffset) const override;
255
256 void serialize(QDataStream &ds) const override;
257
258private:
259 void init(const QByteArray &zoneId, int offsetSeconds, const QString &name,
260 const QString &abbreviation, QLocale::Territory territory,
261 const QString &comment);
262
263 QString m_name;
264 QString m_abbreviation;
265 QString m_comment;
266 QLocale::Territory m_territory;
267 int m_offsetFromUtc;
268};
269
270// Platform backend cascade: match newBackendTimeZone() in qtimezone.cpp
271#if QT_CONFIG(timezone_tzdb)
272class QChronoTimeZonePrivate final : public QTimeZonePrivate
273{
274 bool operator=(const QChronoTimeZonePrivate &) const = delete;
275 QChronoTimeZonePrivate(const QChronoTimeZonePrivate &) = default;
276public:
277 QChronoTimeZonePrivate();
278 QChronoTimeZonePrivate(QByteArrayView id);
279 ~QChronoTimeZonePrivate() override;
280 QChronoTimeZonePrivate *clone() const override;
281
282 QByteArray systemTimeZoneId() const override;
283
284 QString abbreviation(qint64 atMSecsSinceEpoch) const override;
285 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
286 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
287 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
288
289 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
290 QList<QByteArray> availableTimeZoneIds() const override;
291 QList<QByteArray> availableTimeZoneIds(int utcOffset) const override;
292
293 bool hasDaylightTime() const override;
294 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
295
296 Data data(qint64 forMSecsSinceEpoch) const override;
297
298 bool hasTransitions() const override;
299 Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
300 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
301
302private:
303 const std::chrono::time_zone *const m_timeZone;
304};
305#elif defined(Q_OS_DARWIN)
306class Q_AUTOTEST_EXPORT QMacTimeZonePrivate final : public QTimeZonePrivate
307{
308 bool operator=(const QMacTimeZonePrivate &) const = delete;
309 QMacTimeZonePrivate(const QMacTimeZonePrivate &other);
310public:
311 // Create default time zone
312 QMacTimeZonePrivate();
313 // Create named time zone
314 QMacTimeZonePrivate(const QByteArray &ianaId);
315 ~QMacTimeZonePrivate();
316
317 QMacTimeZonePrivate *clone() const override;
318
319 QString comment() const override;
320
321 using QTimeZonePrivate::displayName;
322 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
323 const QLocale &locale) const override;
324 QString abbreviation(qint64 atMSecsSinceEpoch) const override;
325
326 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
327 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
328 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
329
330 bool hasDaylightTime() const override;
331 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
332
333 using QTimeZonePrivate::data;
334 Data data(qint64 forMSecsSinceEpoch) const override;
335
336 bool hasTransitions() const override;
337 Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
338 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
339
340 QByteArray systemTimeZoneId() const override;
341 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
342 QList<QByteArray> availableTimeZoneIds() const override;
343
344 NSTimeZone *nsTimeZone() const;
345
346private:
347 void init(const QByteArray &zoneId);
348
349 NSTimeZone *m_nstz;
350};
351#elif defined(Q_OS_ANDROID)
352class QAndroidTimeZonePrivate final : public QTimeZonePrivate
353{
354 bool operator=(const QAndroidTimeZonePrivate &) const = delete;
355 QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &) = default;
356public:
357 // Create default time zone
358 QAndroidTimeZonePrivate();
359 // Create named time zone
360 QAndroidTimeZonePrivate(const QByteArray &ianaId);
361 ~QAndroidTimeZonePrivate();
362
363 QAndroidTimeZonePrivate *clone() const override;
364
365 using QTimeZonePrivate::displayName;
366 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
367 const QLocale &locale) const override;
368 QString abbreviation(qint64 atMSecsSinceEpoch) const override;
369
370 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
371 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
372 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
373
374 bool hasDaylightTime() const override;
375 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
376
377 using QTimeZonePrivate::data;
378 Data data(qint64 forMSecsSinceEpoch) const override;
379
380 QByteArray systemTimeZoneId() const override;
381 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
382 QList<QByteArray> availableTimeZoneIds() const override;
383
384private:
385 void init(const QByteArray &zoneId);
386
387 QJniObject androidTimeZone;
388};
389#elif defined(Q_OS_UNIX)
390struct QTzTransitionTime
391{
392 qint64 atMSecsSinceEpoch;
393 quint8 ruleIndex;
394};
395Q_DECLARE_TYPEINFO(QTzTransitionTime, Q_PRIMITIVE_TYPE);
396struct QTzTransitionRule
397{
398 int stdOffset = 0;
399 int dstOffset = 0;
400 quint8 abbreviationIndex = 0;
401};
402Q_DECLARE_TYPEINFO(QTzTransitionRule, Q_PRIMITIVE_TYPE);
403constexpr inline bool operator==(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
404{ return lhs.stdOffset == rhs.stdOffset && lhs.dstOffset == rhs.dstOffset && lhs.abbreviationIndex == rhs.abbreviationIndex; }
405constexpr inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept
406{ return !operator==(lhs, rhs); }
407
408// These are stored separately from QTzTimeZonePrivate so that they can be
409// cached, avoiding the need to re-parse them from disk constantly.
410struct QTzTimeZoneCacheEntry
411{
412 QList<QTzTransitionTime> m_tranTimes;
413 QList<QTzTransitionRule> m_tranRules;
414 QList<QByteArray> m_abbreviations;
415 QByteArray m_posixRule;
416 QTzTransitionRule m_preZoneRule;
417 bool m_hasDst = false;
418};
419
420class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate
421{
422 bool operator=(const QTzTimeZonePrivate &) const = delete;
423 QTzTimeZonePrivate(const QTzTimeZonePrivate &) = default;
424public:
425 // Create default time zone
426 QTzTimeZonePrivate();
427 // Create named time zone
428 QTzTimeZonePrivate(const QByteArray &ianaId);
429 ~QTzTimeZonePrivate();
430
431 QTzTimeZonePrivate *clone() const override;
432
433 QLocale::Territory territory() const override;
434 QString comment() const override;
435
436 using QTimeZonePrivate::displayName;
437 QString displayName(QTimeZone::TimeType timeType,
438 QTimeZone::NameType nameType,
439 const QLocale &locale) const override;
440 QString abbreviation(qint64 atMSecsSinceEpoch) const override;
441
442 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
443 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
444 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
445
446 bool hasDaylightTime() const override;
447 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
448
449 Data data(qint64 forMSecsSinceEpoch) const override;
450 Data data(QTimeZone::TimeType timeType) const override;
451 bool isDataLocale(const QLocale &locale) const override;
452
453 bool hasTransitions() const override;
454 Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
455 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
456
457 QByteArray systemTimeZoneId() const override;
458
459 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
460 QList<QByteArray> availableTimeZoneIds() const override;
461 QList<QByteArray> availableTimeZoneIds(QLocale::Territory territory) const override;
462
463private:
464 static QByteArray staticSystemTimeZoneId();
465 QList<QTimeZonePrivate::Data> getPosixTransitions(qint64 msNear) const;
466
467 Data dataForTzTransition(QTzTransitionTime tran) const;
468 Data dataFromRule(QTzTransitionRule rule, qint64 msecsSinceEpoch) const;
469 QTzTimeZoneCacheEntry cached_data;
470 const QList<QTzTransitionTime> &tranCache() const { return cached_data.m_tranTimes; }
471};
472#elif QT_CONFIG(icu)
473class Q_AUTOTEST_EXPORT QIcuTimeZonePrivate final : public QTimeZonePrivate
474{
475 bool operator=(const QIcuTimeZonePrivate &) const = delete;
476 QIcuTimeZonePrivate(const QIcuTimeZonePrivate &other);
477public:
478 // Create default time zone
479 QIcuTimeZonePrivate();
480 // Create named time zone
481 QIcuTimeZonePrivate(const QByteArray &ianaId);
482 ~QIcuTimeZonePrivate();
483
484 QIcuTimeZonePrivate *clone() const override;
485
486 using QTimeZonePrivate::displayName;
487 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
488 const QLocale &locale) const override;
489
490 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
491 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
492 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
493
494 bool hasDaylightTime() const override;
495 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
496
497 using QTimeZonePrivate::data;
498 Data data(qint64 forMSecsSinceEpoch) const override;
499
500 bool hasTransitions() const override;
501 Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
502 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
503
504 QByteArray systemTimeZoneId() const override;
505
506 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override;
507 QList<QByteArray> availableTimeZoneIds() const override;
508 QList<QByteArray> availableTimeZoneIds(QLocale::Territory territory) const override;
509 QList<QByteArray> availableTimeZoneIds(int offsetFromUtc) const override;
510
511private:
512 void init(const QByteArray &ianaId);
513
514 UCalendar *m_ucal;
515};
516#elif defined(Q_OS_WIN)
517class Q_AUTOTEST_EXPORT QWinTimeZonePrivate final : public QTimeZonePrivate
518{
519 bool operator=(const QWinTimeZonePrivate &) const = delete;
520 QWinTimeZonePrivate(const QWinTimeZonePrivate &) = default;
521public:
522 struct QWinTransitionRule {
523 int startYear;
524 int standardTimeBias;
525 int daylightTimeBias;
526 SYSTEMTIME standardTimeRule;
527 SYSTEMTIME daylightTimeRule;
528 };
529
530 // Create default time zone
531 QWinTimeZonePrivate();
532 // Create named time zone
533 QWinTimeZonePrivate(const QByteArray &ianaId);
534 ~QWinTimeZonePrivate();
535
536 QWinTimeZonePrivate *clone() const override;
537
538 QString comment() const override;
539
540 using QTimeZonePrivate::displayName;
541 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType,
542 const QLocale &locale) const override;
543 QString abbreviation(qint64 atMSecsSinceEpoch) const override;
544
545 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override;
546 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override;
547 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override;
548
549 bool hasDaylightTime() const override;
550 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override;
551
552 using QTimeZonePrivate::data;
553 Data data(qint64 forMSecsSinceEpoch) const override;
554
555 bool hasTransitions() const override;
556 Data nextTransition(qint64 afterMSecsSinceEpoch) const override;
557 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override;
558
559 QByteArray systemTimeZoneId() const override;
560
561 QList<QByteArray> availableTimeZoneIds() const override;
562
563 // For use within implementation's TransitionTimePair:
564 QTimeZonePrivate::Data ruleToData(const QWinTransitionRule &rule, qint64 atMSecsSinceEpoch,
565 QTimeZone::TimeType type, bool fakeDst = false) const;
566private:
567 void init(const QByteArray &ianaId);
568
569 QByteArray m_windowsId;
570 QString m_displayName;
571 QString m_standardName;
572 QString m_daylightName;
573 QList<QWinTransitionRule> m_tranRules;
574};
575#endif // C++20, Darwin, Android, Unix, ICU, Win.
576
577QT_END_NAMESPACE
578
579#endif // QTIMEZONEPRIVATE_P_H
580

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