113QGregorianCalendar::matchCenturyToWeekday(
const QCalendar::YearMonthDay &parts,
int dow)
const
116
117
118
119
120
121 auto maybe = julianFromParts(parts.year, parts.month, parts.day);
123 int diff = weekDayOfJulian(*maybe) - dow;
126 int year = parts.year < 0 ? parts.year + 1 : parts.year;
129 const auto yearSplit = qDivMod<100>(year - (parts.month < 3 ? 1 : 0));
130 const int centuryMod4 = qMod<4>(yearSplit.quotient);
132 static_assert(qMod<7>(36524) == 5);
135 if (qMod<7>(diff * 4 + centuryMod4) < 4) {
137 year += (((qMod<7>(diff) + 3) / 2) % 4 - 1) * 100;
138 maybe = julianFromParts(year > 0 ? year : year - 1, parts.month, parts.day);
139 if (maybe && weekDayOfJulian(*maybe) == dow)
141 Q_ASSERT(parts.month == 2 && parts.day == 29
142 && dow !=
int(Qt::Tuesday) && !(year % 100));
145 }
else if (parts.month == 2 && parts.day == 29) {
146 int year = parts.year < 0 ? parts.year + 1 : parts.year;
148 const auto yearSplit = qDivMod<100>(year);
149 if (!yearSplit.remainder) {
150 const auto centuryMod4 = qMod<4>(yearSplit.quotient);
151 Q_ASSERT(centuryMod4);
152 if (centuryMod4 == 1)
155 year += (4 - centuryMod4) * 100;
156 maybe = julianFromParts(year > 0 ? year : year - 1, parts.month, parts.day);
157 if (maybe && weekDayOfJulian(*maybe) == dow)
159 Q_ASSERT(dow !=
int(Qt::Tuesday));
162 return (std::numeric_limits<qint64>::min)();
172int QGregorianCalendar::yearSharingWeekDays(QDate date)
189 static_assert((400 * 365 + 97) % 7 == 0);
195 const int year = date.year();
196 int res = (year < 1970
197 ? 2400 - (2000 - (year < 0 ? year + 1 : year)) % 400
198 : year > 2399 ? 2000 + (year - 2000) % 400 : year);
201 const int lastTwo = res % 100;
202 if (lastTwo == date.month() || lastTwo == date.day()) {
203 Q_ASSERT(lastTwo && !(lastTwo & ~31));
205 static constexpr int usual[] = { 2198, 2199, 2098, 2099, 2399, 2298, 2299 };
206 static constexpr int leaps[] = { 2396, 2284, 2296, 2184, 2196, 2084, 2096 };
209 res = (leapTest(year) ? leaps : usual)[yearStartWeekDay(year) - 1];
211 Q_ASSERT(QDate(res, 1, 1).dayOfWeek() == QDate(year, 1, 1).dayOfWeek());
212 Q_ASSERT(QDate(res, 12, 31).dayOfWeek() == QDate(year, 12, 31).dayOfWeek());
214 Q_ASSERT(res >= 1970 && res <= 2400);
234std::optional<qint64> QGregorianCalendar::julianFromParts(
int year,
int month,
int day)
236 if (!validParts(year, month, day))
239 const auto yearDays = yearMonthToYearDays(year, month);
240 const qint64 y = yearDays.year;
241 const qint64 fromYear = 365 * y + qDiv<4>(y) - qDiv<100>(y) + qDiv<400>(y);
242 return fromYear + yearDays.days + day + BaseJd;
245QCalendar::YearMonthDay QGregorianCalendar::partsFromJulian(qint64 jd)
247 const qint64 dayNumber = jd - BaseJd;
248 const qint64 century = qDiv<FourCenturies>(4 * dayNumber - 1);
249 const int dayInCentury = dayNumber - qDiv<4>(FourCenturies * century);
251 const int yearInCentury = qDiv<FourYears>(4 * dayInCentury - 1);
252 const int dayInYear = dayInCentury - qDiv<4>(FourYears * yearInCentury);
253 const int m = qDiv<FiveMonths>(5 * dayInYear - 3);
254 Q_ASSERT(m < 12 && m >= 0);
256 const int yearOffset = m < 10 ? 0 : 1;
258 const int y = 100 * century + yearInCentury + yearOffset;
259 const int month = m + 3 - 12 * yearOffset;
260 const int day = dayInYear - qDiv<5>(FiveMonths * m + 2);
263 return QCalendar::YearMonthDay(y > 0 ? y : y - 1, month, day);