1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2013 John Layt <jlayt@kde.org> 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtCore module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see https://www.qt.io/terms-conditions. For further 15 ** information use the contact form at https://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 3 as published by the Free Software 20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 21 ** packaging of this file. Please review the following information to 22 ** ensure the GNU Lesser General Public License version 3 requirements 23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 2.0 or (at your option) the GNU General 28 ** Public license version 3 or any later version approved by the KDE Free 29 ** Qt Foundation. The licenses are as published by the Free Software 30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31 ** included in the packaging of this file. Please review the following 32 ** information to ensure the GNU General Public License requirements will 33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34 ** https://www.gnu.org/licenses/gpl-3.0.html. 35 ** 36 ** $QT_END_LICENSE$ 37 ** 38 ****************************************************************************/ 39 40 41 #ifndef QTIMEZONEPRIVATE_P_H 42 #define QTIMEZONEPRIVATE_P_H 43 44 // 45 // W A R N I N G 46 // ------------- 47 // 48 // This file is not part of the Qt API. It exists for the convenience 49 // of internal files. This header file may change from version to version 50 // without notice, or even be removed. 51 // 52 // We mean it. 53 // 54 55 #include "qtimezone.h" 56 #include "private/qlocale_p.h" 57 #include "qvector.h" 58 59 #if QT_CONFIG(icu) 60 #include <unicode/ucal.h> 61 #endif 62 63 #ifdef Q_OS_DARWIN 64 Q_FORWARD_DECLARE_OBJC_CLASS(NSTimeZone); 65 #endif // Q_OS_DARWIN 66 67 #ifdef Q_OS_WIN 68 #include <qt_windows.h> 69 #endif // Q_OS_WIN 70 71 #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) 72 #include <QtCore/private/qjni_p.h> 73 #endif 74 75 QT_BEGIN_NAMESPACE 76 77 class Q_AUTOTEST_EXPORT QTimeZonePrivate : public QSharedData 78 { 79 public: 80 //Version of QTimeZone::OffsetData struct using msecs for efficiency 81 struct Data { 82 QString abbreviation; 83 qint64 atMSecsSinceEpoch; 84 int offsetFromUtc; 85 int standardTimeOffset; 86 int daylightTimeOffset; 87 }; 88 typedef QVector<Data> DataList; 89 90 // Create null time zone 91 QTimeZonePrivate(); 92 QTimeZonePrivate(const QTimeZonePrivate &other); 93 virtual ~QTimeZonePrivate(); 94 95 virtual QTimeZonePrivate *clone() const; 96 97 bool operator==(const QTimeZonePrivate &other) const; 98 bool operator!=(const QTimeZonePrivate &other) const; 99 100 bool isValid() const; 101 102 QByteArray id() const; 103 virtual QLocale::Country country() const; 104 virtual QString comment() const; 105 106 virtual QString displayName(qint64 atMSecsSinceEpoch, 107 QTimeZone::NameType nameType, 108 const QLocale &locale) const; 109 virtual QString displayName(QTimeZone::TimeType timeType, 110 QTimeZone::NameType nameType, 111 const QLocale &locale) const; 112 virtual QString abbreviation(qint64 atMSecsSinceEpoch) const; 113 114 virtual int offsetFromUtc(qint64 atMSecsSinceEpoch) const; 115 virtual int standardTimeOffset(qint64 atMSecsSinceEpoch) const; 116 virtual int daylightTimeOffset(qint64 atMSecsSinceEpoch) const; 117 118 virtual bool hasDaylightTime() const; 119 virtual bool isDaylightTime(qint64 atMSecsSinceEpoch) const; 120 121 virtual Data data(qint64 forMSecsSinceEpoch) const; 122 Data dataForLocalTime(qint64 forLocalMSecs, int hint) const; 123 124 virtual bool hasTransitions() const; 125 virtual Data nextTransition(qint64 afterMSecsSinceEpoch) const; 126 virtual Data previousTransition(qint64 beforeMSecsSinceEpoch) const; 127 DataList transitions(qint64 fromMSecsSinceEpoch, qint64 toMSecsSinceEpoch) const; 128 129 virtual QByteArray systemTimeZoneId() const; 130 131 virtual bool isTimeZoneIdAvailable(const QByteArray &ianaId) const; 132 virtual QList<QByteArray> availableTimeZoneIds() const; 133 virtual QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const; 134 virtual QList<QByteArray> availableTimeZoneIds(int utcOffset) const; 135 136 virtual void serialize(QDataStream &ds) const; 137 138 // Static Utility Methods maxMSecs()139 static inline qint64 maxMSecs() { return std::numeric_limits<qint64>::max(); } minMSecs()140 static inline qint64 minMSecs() { return std::numeric_limits<qint64>::min() + 1; } invalidMSecs()141 static inline qint64 invalidMSecs() { return std::numeric_limits<qint64>::min(); } invalidSeconds()142 static inline qint64 invalidSeconds() { return std::numeric_limits<int>::min(); } 143 static Data invalidData(); 144 static QTimeZone::OffsetData invalidOffsetData(); 145 static QTimeZone::OffsetData toOffsetData(const Data &data); 146 static bool isValidId(const QByteArray &ianaId); 147 static QString isoOffsetFormat(int offsetFromUtc); 148 149 static QByteArray ianaIdToWindowsId(const QByteArray &ianaId); 150 static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId); 151 static QByteArray windowsIdToDefaultIanaId(const QByteArray &windowsId, 152 QLocale::Country country); 153 static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId); 154 static QList<QByteArray> windowsIdToIanaIds(const QByteArray &windowsId, 155 QLocale::Country country); 156 157 // returns "UTC" QString and QByteArray utcQString()158 Q_REQUIRED_RESULT static inline QString utcQString() 159 { 160 return QStringLiteral("UTC"); 161 } 162 utcQByteArray()163 Q_REQUIRED_RESULT static inline QByteArray utcQByteArray() 164 { 165 return QByteArrayLiteral("UTC"); 166 } 167 168 protected: 169 QByteArray m_id; 170 }; 171 Q_DECLARE_TYPEINFO(QTimeZonePrivate::Data, Q_MOVABLE_TYPE); 172 173 template<> QTimeZonePrivate *QSharedDataPointer<QTimeZonePrivate>::clone(); 174 175 class Q_AUTOTEST_EXPORT QUtcTimeZonePrivate final : public QTimeZonePrivate 176 { 177 public: 178 // Create default UTC time zone 179 QUtcTimeZonePrivate(); 180 // Create named time zone 181 QUtcTimeZonePrivate(const QByteArray &utcId); 182 // Create offset from UTC 183 QUtcTimeZonePrivate(int offsetSeconds); 184 // Create custom offset from UTC 185 QUtcTimeZonePrivate(const QByteArray &zoneId, int offsetSeconds, const QString &name, 186 const QString &abbreviation, QLocale::Country country, 187 const QString &comment); 188 QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other); 189 virtual ~QUtcTimeZonePrivate(); 190 191 // Fall-back for UTC[+-]\d+(:\d+){,2} IDs. 192 static qint64 offsetFromUtcString(const QByteArray &id); 193 194 QUtcTimeZonePrivate *clone() const override; 195 196 Data data(qint64 forMSecsSinceEpoch) const override; 197 198 QLocale::Country country() const override; 199 QString comment() const override; 200 201 QString displayName(QTimeZone::TimeType timeType, 202 QTimeZone::NameType nameType, 203 const QLocale &locale) const override; 204 QString abbreviation(qint64 atMSecsSinceEpoch) const override; 205 206 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override; 207 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override; 208 209 QByteArray systemTimeZoneId() const override; 210 211 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override; 212 QList<QByteArray> availableTimeZoneIds() const override; 213 QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override; 214 QList<QByteArray> availableTimeZoneIds(int utcOffset) const override; 215 216 void serialize(QDataStream &ds) const override; 217 218 private: 219 void init(const QByteArray &zoneId); 220 void init(const QByteArray &zoneId, int offsetSeconds, const QString &name, 221 const QString &abbreviation, QLocale::Country country, 222 const QString &comment); 223 224 QString m_name; 225 QString m_abbreviation; 226 QString m_comment; 227 QLocale::Country m_country; 228 int m_offsetFromUtc; 229 }; 230 231 #if QT_CONFIG(icu) 232 class Q_AUTOTEST_EXPORT QIcuTimeZonePrivate final : public QTimeZonePrivate 233 { 234 public: 235 // Create default time zone 236 QIcuTimeZonePrivate(); 237 // Create named time zone 238 QIcuTimeZonePrivate(const QByteArray &ianaId); 239 QIcuTimeZonePrivate(const QIcuTimeZonePrivate &other); 240 ~QIcuTimeZonePrivate(); 241 242 QIcuTimeZonePrivate *clone() const override; 243 244 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType, 245 const QLocale &locale) const override; 246 QString abbreviation(qint64 atMSecsSinceEpoch) const override; 247 248 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override; 249 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override; 250 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override; 251 252 bool hasDaylightTime() const override; 253 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override; 254 255 Data data(qint64 forMSecsSinceEpoch) const override; 256 257 bool hasTransitions() const override; 258 Data nextTransition(qint64 afterMSecsSinceEpoch) const override; 259 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override; 260 261 QByteArray systemTimeZoneId() const override; 262 263 QList<QByteArray> availableTimeZoneIds() const override; 264 QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override; 265 QList<QByteArray> availableTimeZoneIds(int offsetFromUtc) const override; 266 267 private: 268 void init(const QByteArray &ianaId); 269 270 UCalendar *m_ucal; 271 }; 272 #endif 273 274 #if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_EMBEDDED)) 275 struct QTzTransitionTime 276 { 277 qint64 atMSecsSinceEpoch; 278 quint8 ruleIndex; 279 }; 280 Q_DECLARE_TYPEINFO(QTzTransitionTime, Q_PRIMITIVE_TYPE); 281 struct QTzTransitionRule 282 { 283 int stdOffset; 284 int dstOffset; 285 quint8 abbreviationIndex; 286 }; 287 Q_DECLARE_TYPEINFO(QTzTransitionRule, Q_PRIMITIVE_TYPE); 288 Q_DECL_CONSTEXPR inline bool operator==(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept 289 { return lhs.stdOffset == rhs.stdOffset && lhs.dstOffset == rhs.dstOffset && lhs.abbreviationIndex == rhs.abbreviationIndex; } 290 Q_DECL_CONSTEXPR inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept 291 { return !operator==(lhs, rhs); } 292 293 // These are stored separately from QTzTimeZonePrivate so that they can be 294 // cached, avoiding the need to re-parse them from disk constantly. 295 struct QTzTimeZoneCacheEntry 296 { 297 QVector<QTzTransitionTime> m_tranTimes; 298 QVector<QTzTransitionRule> m_tranRules; 299 QList<QByteArray> m_abbreviations; 300 QByteArray m_posixRule; 301 }; 302 303 class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate 304 { 305 QTzTimeZonePrivate(const QTzTimeZonePrivate &) = default; 306 public: 307 // Create default time zone 308 QTzTimeZonePrivate(); 309 // Create named time zone 310 QTzTimeZonePrivate(const QByteArray &ianaId); 311 ~QTzTimeZonePrivate(); 312 313 QTzTimeZonePrivate *clone() const override; 314 315 QLocale::Country country() const override; 316 QString comment() const override; 317 318 QString displayName(qint64 atMSecsSinceEpoch, 319 QTimeZone::NameType nameType, 320 const QLocale &locale) const override; 321 QString displayName(QTimeZone::TimeType timeType, 322 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 Data data(qint64 forMSecsSinceEpoch) const override; 334 335 bool hasTransitions() const override; 336 Data nextTransition(qint64 afterMSecsSinceEpoch) const override; 337 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override; 338 339 QByteArray systemTimeZoneId() const override; 340 341 bool isTimeZoneIdAvailable(const QByteArray &ianaId) const override; 342 QList<QByteArray> availableTimeZoneIds() const override; 343 QList<QByteArray> availableTimeZoneIds(QLocale::Country country) const override; 344 345 private: 346 void init(const QByteArray &ianaId); 347 QVector<QTimeZonePrivate::Data> getPosixTransitions(qint64 msNear) const; 348 349 Data dataForTzTransition(QTzTransitionTime tran) const; 350 #if QT_CONFIG(icu) 351 mutable QSharedDataPointer<QTimeZonePrivate> m_icu; 352 #endif 353 QTzTimeZoneCacheEntry cached_data; tranCache()354 QVector<QTzTransitionTime> tranCache() const { return cached_data.m_tranTimes; } 355 }; 356 #endif // Q_OS_UNIX 357 358 #ifdef Q_OS_MAC 359 class Q_AUTOTEST_EXPORT QMacTimeZonePrivate final : public QTimeZonePrivate 360 { 361 public: 362 // Create default time zone 363 QMacTimeZonePrivate(); 364 // Create named time zone 365 QMacTimeZonePrivate(const QByteArray &ianaId); 366 QMacTimeZonePrivate(const QMacTimeZonePrivate &other); 367 ~QMacTimeZonePrivate(); 368 369 QMacTimeZonePrivate *clone() const override; 370 371 QString comment() const override; 372 373 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType, 374 const QLocale &locale) const override; 375 QString abbreviation(qint64 atMSecsSinceEpoch) const override; 376 377 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override; 378 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override; 379 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override; 380 381 bool hasDaylightTime() const override; 382 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override; 383 384 Data data(qint64 forMSecsSinceEpoch) const override; 385 386 bool hasTransitions() const override; 387 Data nextTransition(qint64 afterMSecsSinceEpoch) const override; 388 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override; 389 390 QByteArray systemTimeZoneId() const override; 391 392 QList<QByteArray> availableTimeZoneIds() const override; 393 394 NSTimeZone *nsTimeZone() const; 395 396 private: 397 void init(const QByteArray &zoneId); 398 399 NSTimeZone *m_nstz; 400 }; 401 #endif // Q_OS_MAC 402 403 #ifdef Q_OS_WIN 404 class Q_AUTOTEST_EXPORT QWinTimeZonePrivate final : public QTimeZonePrivate 405 { 406 public: 407 struct QWinTransitionRule { 408 int startYear; 409 int standardTimeBias; 410 int daylightTimeBias; 411 SYSTEMTIME standardTimeRule; 412 SYSTEMTIME daylightTimeRule; 413 }; 414 415 // Create default time zone 416 QWinTimeZonePrivate(); 417 // Create named time zone 418 QWinTimeZonePrivate(const QByteArray &ianaId); 419 QWinTimeZonePrivate(const QWinTimeZonePrivate &other); 420 ~QWinTimeZonePrivate(); 421 422 QWinTimeZonePrivate *clone() const override; 423 424 QString comment() const override; 425 426 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType, 427 const QLocale &locale) const override; 428 QString abbreviation(qint64 atMSecsSinceEpoch) const override; 429 430 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override; 431 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override; 432 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override; 433 434 bool hasDaylightTime() const override; 435 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override; 436 437 Data data(qint64 forMSecsSinceEpoch) const override; 438 439 bool hasTransitions() const override; 440 Data nextTransition(qint64 afterMSecsSinceEpoch) const override; 441 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override; 442 443 QByteArray systemTimeZoneId() const override; 444 445 QList<QByteArray> availableTimeZoneIds() const override; 446 447 private: 448 void init(const QByteArray &ianaId); 449 QTimeZonePrivate::Data ruleToData(const QWinTransitionRule &rule, qint64 atMSecsSinceEpoch, 450 QTimeZone::TimeType type, bool fakeDst = false) const; 451 452 QByteArray m_windowsId; 453 QString m_displayName; 454 QString m_standardName; 455 QString m_daylightName; 456 QList<QWinTransitionRule> m_tranRules; 457 }; 458 #endif // Q_OS_WIN 459 460 #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) 461 class QAndroidTimeZonePrivate final : public QTimeZonePrivate 462 { 463 public: 464 // Create default time zone 465 QAndroidTimeZonePrivate(); 466 // Create named time zone 467 QAndroidTimeZonePrivate(const QByteArray &ianaId); 468 QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &other); 469 ~QAndroidTimeZonePrivate(); 470 471 QAndroidTimeZonePrivate *clone() const override; 472 473 QString displayName(QTimeZone::TimeType timeType, QTimeZone::NameType nameType, 474 const QLocale &locale) const override; 475 QString abbreviation(qint64 atMSecsSinceEpoch) const override; 476 477 int offsetFromUtc(qint64 atMSecsSinceEpoch) const override; 478 int standardTimeOffset(qint64 atMSecsSinceEpoch) const override; 479 int daylightTimeOffset(qint64 atMSecsSinceEpoch) const override; 480 481 bool hasDaylightTime() const override; 482 bool isDaylightTime(qint64 atMSecsSinceEpoch) const override; 483 484 Data data(qint64 forMSecsSinceEpoch) const override; 485 486 bool hasTransitions() const override; 487 Data nextTransition(qint64 afterMSecsSinceEpoch) const override; 488 Data previousTransition(qint64 beforeMSecsSinceEpoch) const override; 489 490 QByteArray systemTimeZoneId() const override; 491 492 QList<QByteArray> availableTimeZoneIds() const override; 493 494 private: 495 void init(const QByteArray &zoneId); 496 497 QJNIObjectPrivate androidTimeZone; 498 499 }; 500 #endif // Q_OS_ANDROID 501 502 QT_END_NAMESPACE 503 504 #endif // QTIMEZONEPRIVATE_P_H 505