diff options
Diffstat (limited to 'src/corelib/time/qmilankoviccalendar.cpp')
-rw-r--r-- | src/corelib/time/qmilankoviccalendar.cpp | 53 |
1 files changed, 26 insertions, 27 deletions
diff --git a/src/corelib/time/qmilankoviccalendar.cpp b/src/corelib/time/qmilankoviccalendar.cpp index 6c72787e36..a3ffa2a305 100644 --- a/src/corelib/time/qmilankoviccalendar.cpp +++ b/src/corelib/time/qmilankoviccalendar.cpp @@ -4,8 +4,7 @@ #include "qglobal.h" #include "qmilankoviccalendar_p.h" #include "qcalendarmath_p.h" -#include <QtCore/qmath.h> -#include <QtCore/qlocale.h> + #include <QtCore/qdatetime.h> QT_BEGIN_NAMESPACE @@ -53,48 +52,48 @@ bool QMilankovicCalendar::isLeapYear(int year) const return false; if (year <= 0) ++year; - if (qMod(year, 4)) + if (qMod<4>(year)) return false; - if (qMod(year, 100) == 0) { - const qint16 century = qMod(qDiv(year, 100), 9); + const auto yeardm = qDivMod<100>(year); + if (yeardm.remainder == 0) { + const qint16 century = qMod<9>(yeardm.quotient); if (century != 2 && century != 6) return false; } return true; } +using namespace QRomanCalendrical; +// End a Milankovic nine-century cycle on 1 BC, Feb 28 (Gregorian Feb 29): +constexpr qint64 MilankovicBaseJd = LeapDayGregorian1Bce; +// Leap years every 4 years, except for 7 turn-of-century years per nine centuries: +constexpr unsigned NineCenturies = 365 * 900 + 900 / 4 - 7; +// When the turn-of-century is a leap year, the century has 25 leap years in it: +constexpr unsigned LeapCentury = 365 * 100 + 25; + bool QMilankovicCalendar::dateToJulianDay(int year, int month, int day, qint64 *jd) const { Q_ASSERT(jd); if (!isDateValid(year, month, day)) return false; - if (year <= 0) - ++year; - const qint16 c0 = month < 3 ? -1 : 0; - const qint16 x1 = month - 12 * c0 - 3; - const qint16 x4 = year + c0; - const qint16 x3 = qDiv(x4, 100); - const qint16 x2 = qMod(x4, 100); - *jd = qDiv(328718 * x3 + 6, 9) - + qDiv(36525 * x2 , 100) - + qDiv(153 * x1 + 2 , 5) - + day + 1721119; + + const auto yearDays = yearMonthToYearDays(year, month); + const auto centuryYear = qDivMod<100>(yearDays.year); + const qint64 fromYear = qDiv<9>(NineCenturies * centuryYear.quotient + 6) + + qDiv<100>(LeapCentury * centuryYear.remainder); + *jd = fromYear + yearDays.days + day + MilankovicBaseJd; return true; } QCalendar::YearMonthDay QMilankovicCalendar::julianDayToDate(qint64 jd) const { - const qint64 k3 = 9 * (jd - 1721120) + 2; - const qint64 x3 = qDiv(k3, 328718); - const qint64 k2 = 100 * qDiv(qMod(k3, 328718), 9) + 99; - const qint64 k1 = qDiv(qMod(k2, 36525), 100) * 5 + 2; - const qint64 x2 = qDiv(k2, 36525); - const qint64 x1 = qDiv(5 * qDiv(qMod(k2, 36525), 100) + 2, 153); - const qint64 c0 = qDiv(x1 + 2, 12); - const int y = 100 * x3 + x2 + c0; - const int month = x1 - 12 * c0 + 3; - const int day = qDiv(qMod(k1, 153), 5) + 1; - return QCalendar::YearMonthDay(y > 0 ? y : y - 1, month, day); + const auto century9Day = qDivMod<NineCenturies>(9 * (jd - MilankovicBaseJd) - 7); + // Its remainder changes by 9 per day, except roughly once per century. + const auto year100Day = qDivMod<LeapCentury>(100 * qDiv<9>(century9Day.remainder) + 99); + // Its remainder changes by 100 per day, except roughly once per year. + const auto ymd = dayInYearToYmd(qDiv<100>(year100Day.remainder)); + const int y = 100 * century9Day.quotient + year100Day.quotient + ymd.year; + return QCalendar::YearMonthDay(y > 0 ? y : y - 1, ymd.month, ymd.day); } QT_END_NAMESPACE |