Change handling of unspecified year in QCalendar::daysInMonth()
Previously, this was specified to return the usual number of days in the month. What the date-time parser needs, though, is the longest that the relevant month can be, in any year. So change its specification to that. This affects all calendar backends, effectively requiring daysInMonth() to treat Unspecified as if it were a leap year. [ChangeLog][QtCore][QCalendar][Important Behavior Changes] The daysInMonth(month, Unspecified) corner case is now specified to return the greatest number of days in that month across all years, where previously it returned the usual number of days in the month. This means QCalendar().daysInMonth(2) is now 29 rather than 28, with similar for other calendars than the Gregorian default. Change-Id: I165599c655df9fbd77700ed38d8860a4e5cca881 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
parent
b612286696
commit
cd442e439b
@ -1259,7 +1259,7 @@ QCalendar::QCalendar(QAnyStringView name)
|
||||
|
||||
Months are numbered consecutively, starting with 1 for the first month of
|
||||
each year. If \a year is \c Unspecified (its default, if not passed), the
|
||||
month's length in a normal year is returned.
|
||||
month's greatest length in any year is returned.
|
||||
|
||||
\sa maximumDaysInMonth(), minimumDaysInMonth()
|
||||
*/
|
||||
|
@ -61,7 +61,7 @@ int QHijriCalendar::daysInMonth(int month, int year) const
|
||||
if (year == 0 || month < 1 || month > 12)
|
||||
return 0;
|
||||
|
||||
if (month == 12 && isLeapYear(year))
|
||||
if (month == 12 && (year == QCalendar::Unspecified || isLeapYear(year)))
|
||||
return 30;
|
||||
|
||||
return month % 2 == 0 ? 29 : 30;
|
||||
|
@ -156,7 +156,8 @@ QCalendar::YearMonthDay QJalaliCalendar::julianDayToDate(qint64 jd) const
|
||||
int QJalaliCalendar::daysInMonth(int month, int year) const
|
||||
{
|
||||
if (year && month > 0 && month <= 12)
|
||||
return month < 7 ? 31 : month < 12 || isLeapYear(year) ? 30 : 29;
|
||||
return month < 7 ? 31 : (month < 12 || year == QCalendar::Unspecified
|
||||
|| isLeapYear(year)) ? 30 : 29;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ int QRomanCalendar::daysInMonth(int month, int year) const
|
||||
return 0;
|
||||
|
||||
if (month == 2)
|
||||
return isLeapYear(year) ? 29 : 28;
|
||||
return year == QCalendar::Unspecified || isLeapYear(year) ? 29 : 28;
|
||||
|
||||
// Long if odd up to July = 7, or if even from 8 = August onwards:
|
||||
return 30 | ((month & 1) ^ (month >> 3));
|
||||
|
@ -11,7 +11,7 @@ class tst_QCalendar : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
void checkYear(const QCalendar &cal, int year, bool normal=false);
|
||||
void checkYear(const QCalendar &cal, int year);
|
||||
|
||||
private slots:
|
||||
void basic_data();
|
||||
@ -75,7 +75,7 @@ static void checkCenturyResolution(const QCalendar &cal, const QCalendar::YearMo
|
||||
}
|
||||
|
||||
// Support for basic():
|
||||
void tst_QCalendar::checkYear(const QCalendar &cal, int year, bool normal)
|
||||
void tst_QCalendar::checkYear(const QCalendar &cal, int year)
|
||||
{
|
||||
const int moons = cal.monthsInYear(year);
|
||||
// Months are numbered from 1 to moons:
|
||||
@ -103,8 +103,8 @@ void tst_QCalendar::checkYear(const QCalendar &cal, int year, bool normal)
|
||||
QVERIFY(cal.isDateValid(year, i, last));
|
||||
QVERIFY(!cal.isDateValid(year, i, 0));
|
||||
QVERIFY(!cal.isDateValid(year, i, last + 1));
|
||||
if (normal) // Unspecified year gets same daysInMonth():
|
||||
QCOMPARE(cal.daysInMonth(i), last);
|
||||
// Unspecified year gets max daysInMonth():
|
||||
QCOMPARE_GE(cal.daysInMonth(i), last);
|
||||
|
||||
checkCenturyResolution(cal, {year, i, (last + 1) / 2});
|
||||
if (QTest::currentTestFailed())
|
||||
@ -114,11 +114,7 @@ void tst_QCalendar::checkYear(const QCalendar &cal, int year, bool normal)
|
||||
QCOMPARE(sum, days);
|
||||
}
|
||||
|
||||
#define CHECKYEAR(cal, year) checkYear(cal, year); \
|
||||
if (QTest::currentTestFailed()) \
|
||||
return
|
||||
|
||||
#define NORMALYEAR(cal, year) checkYear(cal, year, true); \
|
||||
#define CHECKYEAR(cal, year) checkYear(cal, year); \
|
||||
if (QTest::currentTestFailed()) \
|
||||
return
|
||||
|
||||
@ -177,7 +173,7 @@ void tst_QCalendar::basic()
|
||||
}
|
||||
// Either year is non-leap or we have a decade of leap years together;
|
||||
// expect daysInMonth() to treat year the same as unspecified.
|
||||
NORMALYEAR(cal, year);
|
||||
CHECKYEAR(cal, year);
|
||||
}
|
||||
|
||||
void tst_QCalendar::unspecified()
|
||||
@ -189,15 +185,18 @@ void tst_QCalendar::unspecified()
|
||||
const int thisYear = today.year();
|
||||
QCOMPARE(cal.monthsInYear(QCalendar::Unspecified), cal.maximumMonthsInYear());
|
||||
for (int month = cal.maximumMonthsInYear(); month > 0; month--) {
|
||||
const int days = cal.daysInMonth(month);
|
||||
int count = 0;
|
||||
const int maxDays = cal.daysInMonth(month);
|
||||
bool hitMax = false;
|
||||
// 19 years = one Metonic cycle (used by some lunar calendars)
|
||||
for (int i = 19; i > 0; --i) {
|
||||
if (cal.daysInMonth(month, thisYear - i) == days)
|
||||
count++;
|
||||
int days = cal.daysInMonth(month, thisYear - i);
|
||||
if (days == maxDays)
|
||||
hitMax = true;
|
||||
else
|
||||
QCOMPARE_LT(days, maxDays);
|
||||
}
|
||||
// Require a majority of the years tested:
|
||||
QVERIFY2(count > 9, "Default daysInMonth() should be for a normal year");
|
||||
QVERIFY2(hitMax, "Default daysInMonth() should be the longest that month gets");
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user