114QGregorianCalendar::matchCenturyToWeekday(
const QCalendar::YearMonthDay &parts,
int dow)
const
117
118
119
120
121
122 auto maybe = julianFromParts(parts.year, parts.month, parts.day);
124 int diff = weekDayOfJulian(*maybe) - dow;
127 int year = parts.year < 0 ? parts.year + 1 : parts.year;
130 const auto yearSplit = qDivMod<100>(year - (parts.month < 3 ? 1 : 0));
131 const int centuryMod4 = qMod<4>(yearSplit.quotient);
133 static_assert(qMod<7>(36524) == 5);
136 if (qMod<7>(diff * 4 + centuryMod4) < 4) {
138 year += (((qMod<7>(diff) + 3) / 2) % 4 - 1) * 100;
139 maybe = julianFromParts(year > 0 ? year : year - 1, parts.month, parts.day);
140 if (maybe && weekDayOfJulian(*maybe) == dow)
142 Q_ASSERT(parts.month == 2 && parts.day == 29
143 && dow !=
int(Qt::Tuesday) && !(year % 100));
146 }
else if (parts.month == 2 && parts.day == 29) {
147 int year = parts.year < 0 ? parts.year + 1 : parts.year;
149 const auto yearSplit = qDivMod<100>(year);
150 if (!yearSplit.remainder) {
151 const auto centuryMod4 = qMod<4>(yearSplit.quotient);
152 Q_ASSERT(centuryMod4);
153 if (centuryMod4 == 1)
156 year += (4 - centuryMod4) * 100;
157 maybe = julianFromParts(year > 0 ? year : year - 1, parts.month, parts.day);
158 if (maybe && weekDayOfJulian(*maybe) == dow)
160 Q_ASSERT(dow !=
int(Qt::Tuesday));
163 return (std::numeric_limits<qint64>::min)();
173int QGregorianCalendar::yearSharingWeekDays(QDate date)
190 static_assert((400 * 365 + 97) % 7 == 0);
196 const int year = date.year();
197 int res = (year < 1970
198 ? 2400 - (2000 - (year < 0 ? year + 1 : year)) % 400
199 : year > 2399 ? 2000 + (year - 2000) % 400 : year);
202 const int lastTwo = res % 100;
203 if (lastTwo == date.month() || lastTwo == date.day()) {
204 Q_ASSERT(lastTwo && !(lastTwo & ~31));
206 static constexpr int usual[] = { 2198, 2199, 2098, 2099, 2399, 2298, 2299 };
207 static constexpr int leaps[] = { 2396, 2284, 2296, 2184, 2196, 2084, 2096 };
210 res = (leapTest(year) ? leaps : usual)[yearStartWeekDay(year) - 1];
212 Q_ASSERT(QDate(res, 1, 1).dayOfWeek() == QDate(year, 1, 1).dayOfWeek());
213 Q_ASSERT(QDate(res, 12, 31).dayOfWeek() == QDate(year, 12, 31).dayOfWeek());
215 Q_ASSERT(res >= 1970 && res <= 2400);
235std::optional<qint64> QGregorianCalendar::julianFromParts(
int year,
int month,
int day)
237 if (!validParts(year, month, day))
240 const auto yearDays = yearMonthToYearDays(year, month);
241 const qint64 y = yearDays.year;
242 const qint64 fromYear = 365 * y + qDiv<4>(y) - qDiv<100>(y) + qDiv<400>(y);
243 return fromYear + yearDays.days + day + BaseJd;
246QCalendar::YearMonthDay QGregorianCalendar::partsFromJulian(qint64 jd)
248 const qint64 dayNumber = jd - BaseJd;
249 const qint64 century = qDiv<FourCenturies>(4 * dayNumber - 1);
250 const int dayInCentury = dayNumber - qDiv<4>(FourCenturies * century);
252 const int yearInCentury = qDiv<FourYears>(4 * dayInCentury - 1);
253 const int dayInYear = dayInCentury - qDiv<4>(FourYears * yearInCentury);
254 const int m = qDiv<FiveMonths>(5 * dayInYear - 3);
255 Q_ASSERT(m < 12 && m >= 0);
257 const int yearOffset = m < 10 ? 0 : 1;
259 const int y = 100 * century + yearInCentury + yearOffset;
260 const int month = m + 3 - 12 * yearOffset;
261 const int day = dayInYear - qDiv<5>(FiveMonths * m + 2);
264 return QCalendar::YearMonthDay(y > 0 ? y : y - 1, month, day);