summaryrefslogtreecommitdiffstats
path: root/src/corelib/time/qtimezoneprivate_tz.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Decouple the TZ and ICU backends for timezone dataEdward Welbourne12 days1-29/+2
| | | | | | | | | | | | The TZ backend was instantiating an ICU backend to look up display names, which entailed locking of the lazy-evaluated ICU member. Instead, break out how ICU looks up display names into the new timezone_locale feature's code, so that it can be shared between the two backends. Linux thus only needs to build one backend. Task-number: QTBUG-115158 Change-Id: I37ebc9a30f1c0ab6fd32d45dffa9f21355fb868d Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Rework QTZP::displayName() to use locale and data() moreEdward Welbourne12 days1-51/+70
| | | | | | | | | | | | | | | | | | | | | | | We should only use the isoOffsetFormat() version of offset name for QLocale::C - while other locales may coincide with it, we don't know so shouldn't just assume. Add a query for whether a locale is the one used by the backend for the abbreviation in its data() and, when it is, use that abbreviation as short name. The TZ backend was searching its transitions for help with the abbreviation; we can do that also in the base-class, so introduce a data(TimeType) that will search transition history (if available) for a suitable transition from which to take the abbreviation (when appropriate). This shall make displayName() return an empty string in various cases where it did not, before; this is more honest than returning a string that's inappropriate for the locale for which it was meant to be answering. Task-number: QTBUG-114914 Task-number: QTBUG-115158 Task-number: QTBUG-122448 Change-Id: I523229def63aafcd2009b8406b2c3d13f7c01d9c Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QDateTime and zone code: pass types by const ref if not trivial to copyEdward Welbourne2024-04-191-1/+1
| | | | | | | | | | | QTimeZone, QTimeZonePrivate::Data and QString are all big enough to warrant passing by reference. Task-number: QTBUG-122619 Change-Id: I7f2381316e47f40dd0faac0471967162d4ee6031 Reviewed-by: Juha Vuolle <juha.vuolle@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Rym Bouabid <rym.bouabid@qt.io>
* Make QTimeZonePrivate::Data construction easierEdward Welbourne2024-04-191-37/+39
| | | | | | | | | | | | | | Turn QTZP::invalidData() into a default constructor. A second constructor taking needed details avoids exercising that default constructor elsewhere, when the invalid values aren't what we need. All constructed instances now have all members initialized. In the TZ backend, add some PosixZone helpers to create Data objects, reducing the complexity of calculatePosixTransitions(). Task-number: QTBUG-122619 Change-Id: I56557a2f6249d60012355d5d72c662474be76e51 Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
* QTZP_TZ: make PosixZone default constructor replace its invalid()Edward Welbourne2024-04-191-7/+5
| | | | | | | | | | The type is always constructed by brace-initialization otherwise, so just NSDMI-ing its offset to InvalidOffset simplifies the handling of invalid values. Task-number: QTBUG-122619 Change-Id: Ic7173fe6572bf700bb5858a2553750023c267160 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Apply NSDMI to some internal datetime and timezone typesEdward Welbourne2024-04-191-2/+0
| | | | | | | | | | | | | | | | | | | Although parsedRfcDateTime's clients never read utcOffset unless date and time are valid, and never set them to anything valid without also setting utcOffset, let's not leave it uninitialized by default. The TZ file digester didn't actually set QTzTimeZoneCacheEntry except when setting it to true, so let's make sure it's properly initialized to false. The m_preZoneRule was initialized to all-zeros in one branch of its construction, so set it to that by default so that its default constructor leaves no member uninitialized. These types are only constructed in parsers anyway, so the minor cost of setting fields to zero is dwarfed by string manipulations. Task-number: QTBUG-122619 Change-Id: I6c57fc6d33c379af3f7c6de80c4ca47e431f9d92 Reviewed-by: Mate Barany <mate.barany@qt.io>
* Port to QDirListingAhmad Samir2024-03-031-4/+2
| | | | | | | | | | | Use QDirListing in the Bootstrap build instead of QDirIterator. Drive-by changes: - more const variables - use emplace_back() instead of append() where appropriate Change-Id: Ie1f0d03856e557c4bfabfff38a87edc7da86d091 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Also check available in TZ timezone's constructorEdward Welbourne2024-02-281-0/+2
| | | | | | | | | | | | | | | Follow up to commit 00d9a9a9b59650b8e297f91dcc600c377da5bceb - as commented in the QTZ constructor, one of the reasons for the prior "is available" check was to avoid creating TZ cache entries for it; so have the TZ backend also (like ICU) overtly check for availability before trying to find data for the given ID. This duplicates work done later in the constructor, which can perhaps be optimised out later, but is no worse than where we were before the commit mentioned above. Pick-to: 6.7 6.6 6.5 Task-number: QTBUG-121807 Change-Id: Ie0571df2de2bf0a3f4ee767184e58b378e8cb05a Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QTzTimeZoneCache: don't hold mutex while parsing filesMarc Mutz2024-02-161-1/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The QTzTimeZoneCache::findEntry() function is always called with QTzTimeZoneCache::m_mutex held, from its only caller, QTzTimeZoneCache::fetchEntry(). However, findEntry() performs quite heavy parsing, reading e.g. /etc/localtime or a file in /usr/share/zoneinfo/. These files are larger than 2KiB file on my system. Even though findEntry() doesn't touch m_cache during its operation¹, it thus prevents other threads from looking up (and even parsing) other entries in the cache. A straight-forward solution is therefore to drop the mutex in fetchEntry() for the duration of the findEntry() call² and then re-acquire it for the final m_cache.insert(). This means, of course, that more than one thread could parse the same file concurrently, and then one of the thread's result would be discarded. Having the file already in the OS cache makes this probably less of an issue than it sounds, but more complicated protocols are readily implementable, should it become necessary. QTBUG-122138 has a sketch. ¹ It's a static function, so it cannot access NSDMs. ² Incl. the heap allocation required to store the result in QCache. Fixes: QTBUG-122138 Pick-to: 6.7 Change-Id: If0cba6d041fb21a48cbde6b43190662a2c55cd25 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Matthias Rauter <matthias.rauter@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QTzTimeZoneCache: make findEntry() staticMarc Mutz2024-02-121-1/+1
| | | | | | | | | | | | | | It doesn't need access to the members, so making it static both saves the implicit this pointer, and communicates to the reader that this is function doesn't access other QTzTimeZoneCache members. In particular, it proves that it doesn't really need to be called with m_mutex locked, cf. QTBUG-122138. Task-number: QTBUG-122138 Pick-to: 6.7 6.6 6.5 Change-Id: I28c99be8d066c1647aaf7aa256b6400a6dd92955 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Remove extra semi-colonsTasuku Suzuki2024-02-061-1/+1
| | | | | Change-Id: I92fddb36cd136fd1bd627955f15d0559b9942d7e Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
* Work round ICU disagreeing with TZDB about zone transitionsEdward Welbourne2023-10-261-30/+11
| | | | | | | | | | | | | | | | | | | | Since the TZ backend resorts to ICU for display names, we got inconsistent results if they disagree about when transitions happened. Also, ICU uses the current (or only recent history) names for the zone, so one currently not doing DST (Africa/Tripoli) doesn't get a report of its DST name at a historical time when it did DST (but ICU doesn't know about it). Since the ICU backend, in any case, doesn't override the displayName(qint64, ...), we can simply use the QTZP base version instead of overloading in the TZ back-end, so we only delegate to ICU when it might actually help. This also saves duplicating some locking and lazy-initialization code. In the process, turn a unique lock into a scoped lock within a suitable scope. Also, make a comment more grammatical and less verbose. Change-Id: Iaaed1fb6a380be8b4258c43cbc4bacd5784345fb Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
* Fix warning on invalid time-zone lookupEdward Welbourne2023-09-151-1/+1
| | | | | | | | | | | | Amends commit 569dc0de50a46b64763921199a2706ab34d151a9 to still return when no zone file is found with the given name, as the code did before. Attempting to continue past the error was provoking warnings from QIODevice::read(). Pick-to: 6.6.0 6.6 6.5 Task-number: QTBUG-116017 Change-Id: I0e224a6b30a3f32cd925d87ffba4dcb24f9b8568 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Support the TZDIR environment variableEdward Welbourne2023-09-131-23/+48
| | | | | | | | | | | | On Linux / glibc, this overrides the default system location for the zone info. So check for files there first. Break out a function to manage the trying of (now three) zoneinfo directories when opening a file by name relative to there. Pick-to: 6.6 6.5 Task-number: QTBUG-116017 Change-Id: I1f97107aabd9015c0a5543639870f1d70654ca67 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Include all available IANA DB zones for the TZ backendEdward Welbourne2023-05-151-2/+34
| | | | | | | | | | | | | Previously, QTzTimeZonePrivate::availableTimeZoneIds() only reported the zones listed in the zone.tab file, which maps territories to zones. It thus omitted several zones that are provided by the IANA DB, but not the primary zones for any territory. This meant that it was possible to pass a zone name to the constructor successfully, despite isTimeZoneIdAvailable() claiming it isn't available. Pick-to: 6.5 Change-Id: I9e4eb7f4cfe578204951b995f0ad9ffd7eed5f9c Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Minor tidies in the TZ time-zone backendEdward Welbourne2023-04-141-5/+7
| | | | | | | | | | | | | | Taking the size() of a list before append()ing to it saves the need to subtract 1. Add some missing assertions. We can now use sliced(), rather than mid(), to trim a string or byte array. We can do such trimming on a view, rather than allocating for the trimmed part. Change-Id: I8eff46ea6545a66c765c2d79aa1162c3044ca1cf Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Mate Barany <mate.barany@qt.io>
* Recognize POSIX rules as valid timezone IDs for the TZ backendEdward Welbourne2023-03-201-7/+20
| | | | | | | | | | The constructor, via findEntry(), does allow a POSIX rule as a valid ID, so reflect that in the implementation of isTimeZoneIdAvailable(), even though we can't sensibly enumerate all possible POSIX rules in availableTimeZoneIds(). Change-Id: I7fd21d23ce8ce40c7f423b02e18d2e8df30fb952 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Adapt corelib to use QTimeZone in place of Qt::TimeSpecEdward Welbourne2022-12-091-8/+10
| | | | | | | | | This saves (mostly in corelib/time/) some complications that used to arise from needing different code-paths for different time-specs. Task-number: QTBUG-108199 Change-Id: I5dbd09859fce7599f1ba761f8a0bfc4633d0bef9 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Restore end-of-parse reporting to qstrntod()Edward Welbourne2022-11-241-6/+6
| | | | | | | | | | | | | | | | | | Rework QSimpleParsedNumber to store a qsizetype whose sign serves as ok flag (positive is ok, zero and negative are not) and magnitude is the number of characters used. This replaces an endptr that was set to null to indicate !ok, but that deprived us of end-of-parse information, which is needed for number-parsing. In particular, JS's parsing of numbers accepts overflow (where qstrntod() flags it as invalid) as infinity; so qstrntod() does need to say how long the overflowing (but JS-valid, none the less) number-text was. Modify all callers of functions using this (recently-introduced) type and add tests that fail without this fix. Fixes: QTBUG-108628 Change-Id: I416cd213e1fb8101b1af5a6d43615b970a5db9b4 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QLocale: make qstrnto(u)ll not have output argumentsThiago Macieira2022-11-161-11/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | That is, return everything in the return argument. On the SysV ABI, that means everything gets returned in registers, in both 32- and 64-bit platforms (unlike QtPrivate::ParsedNumber). There's a minor but perceptible performance improvement in parsing strings and byte arrays. Before: Parsed string "42" "1234" "-1548860221" Clock (ns) 16.673 18.878 25.517 CPU cycles 46.548 52.704 71.243 Instructions 201 233 331 After: Parsed string "42" "1234" "-1548860221" Clock (ns) 15.577 17.998 24.198 CPU cycles 43.491 49.942 67.552 Instructions 179 211 308 On my Core i7-1165G7 @ 2.80 GHz, the 22-23 instruction gain per iteration results in half the expected clock gain in runtime (22 / 2.8 GHz = 7.8 ns) because of a slightly lower instruction per cycle rate. That's acceptable because we need less speculative execution. Pick-to: 6.4 Task-number: QTBUG-107788 Change-Id: I07ec23f3cb174fb197c3fffd17220fd64d473cc0 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Port from qAsConst() to std::as_const()Marc Mutz2022-10-111-1/+1
| | | | | | | | | | | | | | | | We've been requiring C++17 since Qt 6.0, and our qAsConst use finally starts to bother us (QTBUG-99313), so time to port away from it now. Since qAsConst has exactly the same semantics as std::as_const (down to rvalue treatment, constexpr'ness and noexcept'ness), there's really nothing more to it than a global search-and-replace, with manual unstaging of the actual definition and documentation in dist/, src/corelib/doc/ and src/corelib/global/. Task-number: QTBUG-99313 Change-Id: I4c7114444a325ad4e62d0fcbfd347d2bbfb21541 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
* Port from container.count()/length() to size()Marc Mutz2022-10-041-9/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is semantic patch using ClangTidyTransformator: auto QtContainerClass = expr(hasType(namedDecl(hasAnyName(<classes>)))).bind(o) makeRule(cxxMemberCallExpr(on(QtContainerClass), callee(cxxMethodDecl(hasAnyName({"count", "length"), parameterCountIs(0))))), changeTo(cat(access(o, cat("size"), "()"))), cat("use 'size()' instead of 'count()/length()'")) a.k.a qt-port-to-std-compatible-api with config Scope: 'Container'. <classes> are: // sequential: "QByteArray", "QList", "QQueue", "QStack", "QString", "QVarLengthArray", "QVector", // associative: "QHash", "QMultiHash", "QMap", "QMultiMap", "QSet", // Qt has no QMultiSet Change-Id: Ibe8837be96e8d30d1846881ecd65180c1bc459af Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* PosixZone::parse(): don't reset already-initialized variableEdward Welbourne2022-06-081-2/+1
| | | | | | | | | | | The nameBegin variable was already initialized to pos, so just increment it in the one case that needs it rather than resetting it in both branches of the condition. Change-Id: Ia0d42b604ed21829dc84c27a1907c345f62594d1 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* Use SPDX license identifiersLucie Gérard2022-05-161-40/+4
| | | | | | | | | | | | | Replace the current license disclaimer in files by a SPDX-License-Identifier. Files that have to be modified by hand are modified. License files are organized under LICENSES directory. Task-number: QTBUG-67283 Change-Id: Id880c92784c40f3bbde861c0d93f58151c18b9f1 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
* Exploit the new macro varargs form of Q_GLOBAL_STATICEdward Welbourne2022-04-221-2/+2
| | | | | | | | Convert various uses of Q_GLOBAL_STATIC_WITH_ARGS() to the less verbose form the recent reworking makes possible. Change-Id: I57820660b5d00d39bf54b5a08cb921ebaec57c7c Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Apply Q_CONSTINIT across the codebaseMarc Mutz2022-03-291-1/+1
| | | | | | | | | Still not complete. Just grepping for static and thread_local. Task-number: QTBUG-100486 Change-Id: I90ca14e8db3a95590ecde5f89924cf6fcc9755a3 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Short live Q_CONSTINIT!Marc Mutz2022-03-261-1/+1
| | | | | | | | | | | | | | | | | | It expands to the first available of - constinit (C++20) - [[clang::require_constant_initialization]] (Clang) - __constinit (GCC >= 10) Use it around the code (on and near static QBasicAtomic; this patch makes no attempt to find all statics in qtbase). [ChangeLog][QtCore][QtGlobal] Added macro Q_CONSTINIT. Fixes: QTBUG-100484 Change-Id: I11e0363a7acb3464476859d12ec7f94319d82be7 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* QtCore: replace QLatin1String/QLatin1Char with _L1/u'' where applicableSona Kurazyan2022-03-251-4/+6
| | | | | | | | | | | As a drive-by, did also minor refactorings/improvements. Task-number: QTBUG-98434 Change-Id: I81964176ae2f07ea63674c96f47f9c6aa046854f Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Anton Kudryavtsev <antkudr@mail.ru>
* Core: Do not depend on transitive includesFabian Kosmale2022-03-171-0/+1
| | | | | Change-Id: I2c71188a4d27692a2d6ef1aa447b329627214b17 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
* QTzTimeZonePrivate: make ZoneNameReader constinit'ableMarc Mutz2022-02-091-2/+2
| | | | | | | | | | | | | | It's used as a thread_local static, so it better be. What prevented it was the unused inheritance from QObject and the missing constexpr ctor of the StatIdent() data member. Fixed both. Pick-to: 6.3 Change-Id: I312ed6dc8bf7193cdaa7dc708bf19b018e56ec8a Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* QTzTimeZonePrivate: fix UB (data race on m_icu)Marc Mutz2022-01-121-0/+12
| | | | | | | | | | | | | | | | | | | | | | | | The fallback m_icu QIcuTimeZonePrivate is lazily constructed, which means that two threads each with their own copy of a QTimeZone with a shared QTzTimeZonePrivate will race over who gets to set m_icu, e.g. when concurrently calling QTimeZone::displayName(). Fix by protecting m_icu with a mutex. For simplicity, use a static mutex, not a per-instance one (which would delete the QTzTimeZonePrivate copy constructor, which clone() relies on). This is sufficient for 5.15. For Qt 6, going forward, we could make this lock-less, too. [ChangeLog][QtCore][QTimeZone] Fixed a data race on Unix platforms when implicitly-shared copies of QTimeZone objects were used in certain ways (e.g. calling displayName()) from different threads and Qt was configured with ICU support. Pick-to: 6.3 6.2 5.15 Change-Id: I7e57aef3dd44a90289ad86d0578ece1e54920730 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* QTzTimeZonePrivate: use ctor delegation instead of init()Marc Mutz2022-01-051-8/+8
| | | | | | | | | | | | | | This makes it obvious that the code in init() is only called from the constructor and its m_icu handling doesn't need mutex protection (to be added in a subsequent commit). Since the input to the ctor is the result of a virtual function, factor said virtual into a static function and call that instead. Pick-to: 6.3 6.2 5.15 Change-Id: I7c49f2e865201a2ce2b2d86b19dae29c6d337e0e Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* corelib: Fix typos in source code commentsJonas Kvinge2021-10-121-2/+2
| | | | | | Pick-to: 6.2 Change-Id: Ic78afb67143112468c6f84677ac88f27a74b53aa Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* Convert various callers of strtou?ll() to call strntou?ll()Edward Welbourne2021-08-301-9/+3
| | | | | | | | Where size is known or can readily be determined. Change-Id: I442e7ebb3757fdbf7d021a15e19aeba533b590a5 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* Use time-zone transition data before 1970 as well as afterEdward Welbourne2021-05-261-3/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | QDateTime has long followed a convention of ignoring what it knows about time-zone transitions before the epoch. This produces unhelpful artefacts (such as an ahistorical spring-forward skipping the first hour of 1970 in Europe/London, which was in permanent DST at the time) and complicates the code. It documented that DST transitions were ignored, but in fact ignored all transitions prior to 1970 and simply assumed that the current time-zone properties (half a century later) applied to all times before 1970. This appears to be based on the fact that the MS APIs using time_t all limit their range to after 1970. Given that we have to resort to "other means" to deal with times after the end of time_t, when it's only 32-bit (and after year 3000, on MS systems), we have the means in place to handle times outside the range supported by the system APIs, so have no need to mimic this restriction. (Those means are not as robust as we might want, but they are less bad than assuming that the present zone properites were always in effect prior to 1970.) On macOS, the time_t functions only reach back to the start of 1900; it reaches to the end of its time_t range and Linux covers the whole range. Given this variety, the range is now auto-detected the first time it is needed (based on some quick and dirty heuristics). Various CET-specific tests now need adjustments in tests of times before the introduction of time-zones (when they are in fact on LMT, not CET). The systemZone() test of QTimeZone can now restore its pre-zone test cases. Various comments on tests needed updates. [ChangeLog][QtCore][QDateTime] Available time-zone information is now used to its full extent, where previously QDateTime used LocalTime's current standard time for all dates before 1970. Where we have time-zone information, it is considered reliable, so we use it. This changes the "best efforts" used for times outside the range supported by the system APIs, in most cases giving less misleading results. Fixes: QTBUG-80421 Change-Id: I7b1df7622dd9be244b0238ed9c08845fb5b32215 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Fix mix-guided use of const reference variableEdward Welbourne2021-04-291-1/+1
| | | | | | | | It needs to be a mutable value variable to be std::move()d. Pick-to: 6.1 5.15 Change-Id: I9d78b2975f8964e7a7eb06771b0069d9b9e6661e Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Check POSIX rules during QTzTimeZone creationEdward Welbourne2021-04-271-15/+64
| | | | | | | | | | | | | | | | | | | | | Previously, an apparent POSIX rule would be saved and any defects in it would only be discovered when trying to use it to generate transitions. Instead, check that it has the right form during the initial parsing of its data. In the process, since checking for DST in the process is trivial, implement a long-standing TODO to cache hasDaylightTime()'s answer. The array it scanned was in any case being scanned during construction, so detecting DST in init()'s scan is trivial; and its failure to check the POSIX rule mean it failed to notice when zones entirely specified by a POSIX rule have DST. Adapt a test using a POSIX-only rule to verify it does know the zone has DST; it did not, before this change. Change-Id: I690c013d3331600f7348dae61c35d41e5599da70 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Fix handling of a POSIX zone rule describing permanent DSTEdward Welbourne2021-04-271-17/+44
| | | | | | | | | | | | | | | | | | | | | | | | | The description necessarily has fake transitions at start and end of the year, potentially outside the year. These transitions should not be reported by QTzTimeZonePrivate as transitions, although its data() must find a "transition" whose data it can use (as in the permanent standard time case, which could potentially be represented the same way, although there's a saner way to do so, that the code already handles) to report the zone's properties. In the process, fix (and make more straightforward) the convoluted decision-making code that was deciding which transitions to include in the returned list. It was assuming invalidMSecs() would be set as the atMSecsSinceEpoch of a transition, although this is computed in a way that makes that value most unlikely, even when the result is invalid. It also rather confusingly mixed < 0 tests as tests for overflow with the one < 0 test that's about ignoring DST before 1970. Also added comments to clarify some of what's going on there. Expanded a recently-added test of a permanent DST zone to verify this now works correctly. Change-Id: Ia8d98f433fb1e479dba5479220a62196c30f0244 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Correct the parsing of POSIX rule day-of-year fieldsEdward Welbourne2021-04-271-8/+11
| | | | | | | | | | | | | | | | | There are two formats for such fields: one with a J prefix on a number in the range 1 to 365, the other with no prefix and a range from 0 to 365. The code mistakenly treated the latter as if its range were from 1 to 366. The J-form doesn't count Feb 29th, so March always starts on day 60; the code tried to take that into account, but adjusted in the wrong direction (and this mislead me, in a recent partial fix, into a fence-post error). Add a test-case based on the Africa/Casablanca POSIX rule seen on RHEL 8.2, which tripped over the off-by-one error without a J prefix. This incidentally also tests the J case. Change-Id: I692ca511e5c960f91a6c21073d3b2f037f5e445f Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* In the POSIX zone parser, handle no-DST zones the same as name-onlyEdward Welbourne2021-04-201-3/+3
| | | | | | | | | | | | If parsing the standard time data brings us to the end of the zone info, there is no DST information to use later and it makes sense to record the zone as simply a fixed-offset zone. At the same time, handle the case of empty name in the standard time data; use the zone info as name rather than an empty string. Change-Id: I34d4ea25d93d821a937949730adee89d82105bc9 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Correct the range of allowed hours for a POSIX rule's transitionEdward Welbourne2021-04-201-27/+14
| | | | | | | | | | | | | | | | | | | | A POSIX rule's transition time is allowed an hour in the range from -137 to 137; in particular, a negative hour is allowed, and used by some Greenland zones using Europe's time-of-transition which, as they are more than two hours west of Greenwich, happens before midnight. This means the time of transition can't be represented by a QTime(), so propagate the int that represents it to the code that consumes it; and treat parsing failure as an error rather than "correcting" it - if the transition time is given, it must be valid. Changed tst_QTimeZone::isTimeZoneIdAvailable()'s verification of validity to report the name of the zone it thought was invalid. (A later change, validating POSIX rules, caued this to fail for America/Nuuk without the present fix.) Change-Id: I5c9127ac34d878554dd0aca1c1c7338c7e0e1c28 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Add the "Territory" enumerated type for QLocaleJiDe Zhang2021-04-151-7/+7
| | | | | | | | | | | | | | | | | | | The use of "Country" is misleading as some entries in the enumeration are not countries (eg, HongKong), for all that most are. The Unicode Consortium's Common Locale Data Repository (CLDR, from which QLocale's data is taken) calls these territories, so introduce territory-based names and prepare to deprecate the country-based ones in due course. [ChangeLog][QtCore][QLocale] QLocale now has Territory as an alias for its Country enumeration, and associated territory-based names to match its country-named methods, to better match the usage in relevant standards. The country-based names shall in due course be deprecated in favor of the territory-based names. Fixes: QTBUG-91686 Change-Id: Ia1ae1ad7323867016186fb775c9600cd5113aa42 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Make POSIX transition rule parser more robustEdward Welbourne2021-04-141-14/+29
| | | | | | | | | | | | | | | | | | | | | | | | The POSIX rule parser used by QTzTimeZonePrivate recklessly assumed that, if splitting the rule on a dot produced more than one part, it necessarily produced at least three. That's true for well-formed POSIX rules, but we should catch the case of malformed rules. Likewise, when calculating the dates of transitions, splitting the date rule on dots might produce too few fragments; and the fragments might not parse as valid numbers, or might be out of range for their respective fields in a date. Check all these cases, too. Added a test that crashed previously. Changed QTimeZone::offsetFromUtc() so that its "return zero on invalid" applies also to the case where the backend returns invalid, in support of this. Fixes: QTBUG-92808 Pick-to: 6.1 6.1.0 6.0 5.15 Change-Id: Ica383a7a987465483341bdef8dcfd42edb6b43d6 Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Robert Löhning <robert.loehning@qt.io>
* Restore support for reading /etc/timezone for system zone nameEdward Welbourne2021-03-231-7/+15
| | | | | | | | | | | This restores one of the two mechanisms removed in commit b0383cbd388336f698ceeac11a4f50cdff931dd9, transformed to fit in with the new cached system-zone determination. Fixes: QTBUG-87326 Pick-to: 6.1 6.0 5.15 Change-Id: Ic270acb0d958e17dbc74a0ff93a5a1843c939678 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* QTzTimeZonePrivate: provide correct data for before the first transitionEdward Welbourne2021-03-181-14/+22
| | | | | | | | | | | | | | | | We previously used the data for after the first transition; but the Olson database knows about local mean time for each zone, and it does get used by the system libraries, so systemZone will conflict with LocalTime once we use the time_t functions outside their 32-bit range (coming shortly). Record the pre-zone data during parsing and use it in the (fortunately only one) place that needs it. Discovered the issue in the course of debugging other issues while purging QDateTime of its wilful ignorance of pre-1970 DST. Change-Id: Icf957460fa3ccbaf5165e79f38ac68b450ecf98f Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Use QFile directly instead of via QTextStreamEdward Welbourne2021-03-161-13/+23
| | | | | | | | | | Follows up on a TODO comment that says QTextStream is less efficient. In any case, QFile has readLine() returning QByteArray, without conversion to QString, and the parsing is uncomplicated. Change-Id: I06e563df417692d3b6514a52a313a0ff55b0b52e Reviewed-by: Øystein Heskestad <oystein.heskestad@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Fix handling of Sunday in POSIX time-zone rulesEdward Welbourne2021-02-011-2/+2
| | | | | | | | | | | | | | | | | | | | | Dating from the origins of our support for the zoneinfo file format, the mapping of POSIX's day-numbering (0 = Sunday through 6 = Saturday, see [*]) to Qt's (1 = Monday through 7 = Sunday) was done by mapping 0 to 1, when it should have been 7. [*] http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html Corrected a QTimeZone test that trusted the results it got without checking which day of the week those were: they were all Mondays. Verified that the corrected dates are in fact Sundays. Checked the zone abbreviations, too. Fixes: QTBUG-90553 Pick-to: 6.0 5.15 Change-Id: I84b4b14f9892ff687918cd3c42c7c9807e45313c Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
* QTzTimeZonePrivate::init(): fix handling of empty IDEdward Welbourne2021-01-271-7/+13
| | | | | | | | | | | | | | | | We were using the first abbreviation in the list, where the current time's one is probably more apt. We look up displayName() using ICU, when in use, but that abbreviatio may be unknown to it. So ensure, when using abbreviation in place of empty id, that we get the system zone for ICU, for use if we're asked for the display name. This is a follow up to b12d6c6a8ab5f7b01bdd2cb862a66a409700faa1. Pick-to: 6.0 5.15 Change-Id: I177db55de1ffbc763def8a0423642f2b3da74fa6 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Fix QTzTimeZonePrivate::displayName()'s fallbackEdward Welbourne2021-01-201-1/+2
| | | | | | | | | It previously fell back on abbreviation, a very poor choice. The base class does better than that, so use its implementation instead. Pick-to: 6.0 Change-Id: I47cbfce815cd8b2b533d9c6aeebcf398e5852d02 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Bounds-check time-zone offsets when parsingEdward Welbourne2020-11-271-11/+16
| | | | | | | | | | | | | | | Parsing of time-zone offsets should check the offset string conforms to the expected format and has valid values in its fields. The QDateTime parser, fromOffsetString(), neglected the bounds check on hours; the QTzTimeZonePrivate parser, parsePosixTime(), neglected all upper bounds checks, only checking against negative valus. Drive-by - refined phrasing of a comment. Pick-to: 6.0 5.15 Fixes: QTBUG-88656 Change-Id: If04cdbe65064108eaa87c42310527783ad21b4c0 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>