summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2023-11-24 11:52:31 +0100
committerEdward Welbourne <edward.welbourne@qt.io>2023-12-08 11:40:36 +0100
commitb8fac538032cee6eb6f4e5dcbb5a31485bb59e46 (patch)
tree581cd2961d5a7815421f8d1feea9c7bd68aa6939 /tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp
parentc5864a96a6670d9cece5eaa18cab8c4c339f8706 (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.cpp49
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);