diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2023-11-24 11:52:31 +0100 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2023-12-08 11:40:36 +0100 |
commit | b8fac538032cee6eb6f4e5dcbb5a31485bb59e46 (patch) | |
tree | 581cd2961d5a7815421f8d1feea9c7bd68aa6939 /tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp | |
parent | c5864a96a6670d9cece5eaa18cab8c4c339f8706 (diff) |
Add QCalendar::matchCenturyToWeekday()
This takes a YearMonthDay and a day-of-the-week, returning a QDate
that (if possible, else invalid) has the given day of the week and
differs from the YearMonthDay only in the century. This is useful when
resolving dates with only two-digit year information, which can be
disambiguated by the day of the week. Added tests of the new API.
This adds a new virtual method to QCalendarBackend, for which that
base class does provide a brute force implementation, so derived
classes do not need to add implementations. It is, however, a
binary-incompatible change for any backend plugins that may be in use
to implement custom calendars.
Worked out the details for the Gregorian calendar to make it possible
to compute the right century (and whether any century works) without
trial-and-error searching. Coded that up as its implementation of the
new method.
[ChangeLog][QtCore][QCalendar] Added a matchCenturyToWeekday() method
for use when resolving dates given day, month and last two digits of
the year, along with day of the week. Any custom calendar backend
plugins shall need a recompile and may, optionally, implement the new
virtual method behind this.
Change-Id: I6003c8d9423d6bfb833957bb5120f2d423219c7a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp')
-rw-r--r-- | tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp b/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp index 4eebce6d80..739f9ab1f4 100644 --- a/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp +++ b/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp @@ -31,6 +31,49 @@ private slots: void gregory(); }; +static void checkCenturyResolution(const QCalendar &cal, const QCalendar::YearMonthDay &base) +{ + quint8 weekDayMask = 0; + for (int offset = -7; offset < 8; ++offset) { + const auto probe = QDate(base.year, base.month, base.day, cal).addYears(100 * offset, cal); + const int dow = cal.dayOfWeek(probe); + if (probe.isValid() && dow > 0 && dow < 8) + weekDayMask |= 1 << quint8(dow - 1); + } + for (int j = 1; j < 8; ++j) { + const bool seen = weekDayMask & (1 << quint8(j - 1)); + const QDate check = cal.matchCenturyToWeekday(base, j); + if (check.isValid()) { + const auto parts = cal.partsFromDate(check); + const int dow = cal.dayOfWeek(check); + QCOMPARE(dow, j); + QCOMPARE(parts.day, base.day); + QCOMPARE(parts.month, base.month); + int gap = parts.year - base.year; + if (!cal.hasYearZero() && (parts.year > 0) != (base.year > 0)) + gap += parts.year > 0 ? -1 : +1; + auto report = qScopeGuard([parts, base]() { + qDebug("Wrongly matched year: %d replaced %d", parts.year, base.year); + }); + QCOMPARE(gap % 100, 0); + // We searched 7 centuries each side of base. + if (seen) { + QCOMPARE_LT(gap / 100, 8); + QCOMPARE_GT(gap / 100, -8); + } else { + QVERIFY(gap / 100 >= 8 || gap / 100 <= -8); + } + report.dismiss(); + } else { + auto report = qScopeGuard([j, base]() { + qDebug("Missed dow[%d] for %d/%d/%d", j, base.year, base.month, base.day); + }); + QVERIFY(!seen); + report.dismiss(); + } + } +} + // Support for basic(): void tst_QCalendar::checkYear(const QCalendar &cal, int year, bool normal) { @@ -49,7 +92,7 @@ void tst_QCalendar::checkYear(const QCalendar &cal, int year, bool normal) int sum = 0; const int longest = cal.maximumDaysInMonth(); - for (int i = moons; i > 0; i--) { + for (int i = moons; i > 0; --i) { const int last = cal.daysInMonth(i, year); sum += last; // Valid month has some days and no more than max: @@ -62,6 +105,10 @@ void tst_QCalendar::checkYear(const QCalendar &cal, int year, bool normal) QVERIFY(!cal.isDateValid(year, i, last + 1)); if (normal) // Unspecified year gets same daysInMonth(): QCOMPARE(cal.daysInMonth(i), last); + + checkCenturyResolution(cal, {year, i, (last + 1) / 2}); + if (QTest::currentTestFailed()) + return; } // Months add up to the whole year: QCOMPARE(sum, days); |