diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2023-01-16 18:42:24 +0100 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2023-01-31 17:35:13 +0100 |
commit | 19c913b43d0cadc0fee3081be4043bd6f083f8f7 (patch) | |
tree | 1168246a797f7fdf8fea9a448c565ca6608b3489 /src | |
parent | 0e653246b163adb58d0fd955f45aaefc8a506443 (diff) |
Deploy QRoundingDown::qDivMod() in date-time calculations
This saves duplicate computations and incidentally now fixes some
overflow issues. In the process, simplify some calendrical
calculations.
Fixes: QTBUG-109845
Change-Id: Iee331803e8281bbf822a001722a6faa3e66f6322
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/time/qdatetime.cpp | 6 | ||||
-rw-r--r-- | src/corelib/time/qislamiccivilcalendar.cpp | 10 | ||||
-rw-r--r-- | src/corelib/time/qjuliancalendar.cpp | 14 | ||||
-rw-r--r-- | src/corelib/time/qlocaltime.cpp | 17 | ||||
-rw-r--r-- | src/corelib/time/qmilankoviccalendar.cpp | 30 |
5 files changed, 36 insertions, 41 deletions
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 098b47e31a..c8865bf9cd 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -3053,12 +3053,12 @@ static QPair<QDate, QTime> getDateTime(const QDateTimeData &d) { auto status = getStatus(d); const qint64 msecs = getMSecs(d); - const qint64 days = QRoundingDown::qDiv<MSECS_PER_DAY>(msecs); + const auto dayMilli = QRoundingDown::qDivMod<MSECS_PER_DAY>(msecs); return { status.testFlag(QDateTimePrivate::ValidDate) - ? QDate::fromJulianDay(JULIAN_DAY_FOR_EPOCH + days) + ? QDate::fromJulianDay(JULIAN_DAY_FOR_EPOCH + dayMilli.quotient) : QDate(), status.testFlag(QDateTimePrivate::ValidTime) - ? QTime::fromMSecsSinceStartOfDay(msecs - days * MSECS_PER_DAY) + ? QTime::fromMSecsSinceStartOfDay(dayMilli.remainder) : QTime() }; } diff --git a/src/corelib/time/qislamiccivilcalendar.cpp b/src/corelib/time/qislamiccivilcalendar.cpp index 96b73dcd43..48bb0064c8 100644 --- a/src/corelib/time/qislamiccivilcalendar.cpp +++ b/src/corelib/time/qislamiccivilcalendar.cpp @@ -77,11 +77,11 @@ bool QIslamicCivilCalendar::dateToJulianDay(int year, int month, int day, qint64 QCalendar::YearMonthDay QIslamicCivilCalendar::julianDayToDate(qint64 jd) const { constexpr qint64 epoch = 1948440; - const int32_t k2 = 30 * (jd - epoch) + 15; - const int32_t k1 = 11 * qDiv<30>(qMod<10631>(k2)) + 5; - int y = qDiv<10631>(k2) + 1; - const int month = qDiv<325>(k1) + 1; - const int day = qDiv<11>(qMod<325>(k1)) + 1; + const auto k2dm = qDivMod<10631>(30 * (jd - epoch) + 15); + int y = k2dm.quotient + 1; + const auto k1dm = qDivMod<325>(11 * qDiv<30>(k2dm.remainder) + 5); + const int month = k1dm.quotient + 1; + const int day = qDiv<11>(k1dm.remainder) + 1; return QCalendar::YearMonthDay(y > 0 ? y : y - 1, month, day); } diff --git a/src/corelib/time/qjuliancalendar.cpp b/src/corelib/time/qjuliancalendar.cpp index e1ea27b3d5..1c63d4e170 100644 --- a/src/corelib/time/qjuliancalendar.cpp +++ b/src/corelib/time/qjuliancalendar.cpp @@ -75,14 +75,12 @@ bool QJulianCalendar::dateToJulianDay(int year, int month, int day, qint64 *jd) QCalendar::YearMonthDay QJulianCalendar::julianDayToDate(qint64 jd) const { - const qint64 y2 = jd - 1721118; - const qint64 k2 = 4 * y2 + 3; - const qint64 k1 = 5 * qDiv<4>(qMod<1461>(k2)) + 2; - const qint64 x1 = qDiv<153>(k1); - const qint64 c0 = qDiv<12>(x1 + 2); - const int y = qint16(qDiv<1461>(k2) + c0); - const int month = quint8(x1 - 12 * c0 + 3); - const int day = qDiv<5>(qMod<153>(k1)) + 1; + const auto k2dm = qDivMod<1461>(4 * (jd - 1721118) + 3); + const auto k1dm = qDivMod<153>(5 * qDiv<4>(k2dm.remainder) + 2); + const auto c0dm = qDivMod<12>(k1dm.quotient + 2); + const int y = qint16(k2dm.quotient + c0dm.quotient); + const int month = quint8(c0dm.remainder + 1); + const int day = qDiv<5>(k1dm.remainder) + 1; return QCalendar::YearMonthDay(y > 0 ? y : y - 1, month, day); } diff --git a/src/corelib/time/qlocaltime.cpp b/src/corelib/time/qlocaltime.cpp index 9056695967..3ff603d8dd 100644 --- a/src/corelib/time/qlocaltime.cpp +++ b/src/corelib/time/qlocaltime.cpp @@ -312,8 +312,9 @@ inline bool secondsAndMillisOverflow(qint64 epochSeconds, qint64 millis, qint64 // returns the local milliseconds, offset from UTC and DST status. QDateTimePrivate::ZoneState utcToLocal(qint64 utcMillis) { - const time_t epochSeconds = QRoundingDown::qDiv<MSECS_PER_SEC>(utcMillis); - const int msec = utcMillis - epochSeconds * MSECS_PER_SEC; + const auto epoch = QRoundingDown::qDivMod<MSECS_PER_SEC>(utcMillis); + const time_t epochSeconds = epoch.quotient; + const int msec = epoch.remainder; Q_ASSERT(msec >= 0 && msec < MSECS_PER_SEC); if (qint64(epochSeconds) * MSECS_PER_SEC + msec != utcMillis) // time_t range too narrow return {utcMillis}; @@ -341,10 +342,10 @@ QDateTimePrivate::ZoneState utcToLocal(qint64 utcMillis) QString localTimeAbbbreviationAt(qint64 local, QDateTimePrivate::DaylightStatus dst) { - const qint64 localDays = QRoundingDown::qDiv<MSECS_PER_DAY>(local); - qint64 millis = local - localDays * MSECS_PER_DAY; + const auto localDayMilli = QRoundingDown::qDivMod<MSECS_PER_DAY>(local); + qint64 millis = localDayMilli.remainder; Q_ASSERT(0 <= millis && millis < MSECS_PER_DAY); // Definition of QRD::qDiv. - struct tm tmLocal = timeToTm(localDays, int(millis / MSECS_PER_SEC), dst); + struct tm tmLocal = timeToTm(localDayMilli.quotient, int(millis / MSECS_PER_SEC), dst); time_t utcSecs; if (!callMkTime(&tmLocal, &utcSecs)) return {}; @@ -356,11 +357,11 @@ QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::Dayligh { qint64 localSecs = local / MSECS_PER_SEC; qint64 millis = local - localSecs * MSECS_PER_SEC; // 0 or with same sign as local - const qint64 localDays = QRoundingDown::qDiv<SECS_PER_DAY>(localSecs); - qint64 daySecs = localSecs - localDays * SECS_PER_DAY; + const auto localDaySec = QRoundingDown::qDivMod<SECS_PER_DAY>(localSecs); + qint64 daySecs = localDaySec.remainder; Q_ASSERT(0 <= daySecs && daySecs < SECS_PER_DAY); // Definition of QRD::qDiv. - struct tm tmLocal = timeToTm(localDays, daySecs, dst); + struct tm tmLocal = timeToTm(localDaySec.quotient, daySecs, dst); time_t utcSecs; if (!callMkTime(&tmLocal, &utcSecs)) return {local}; diff --git a/src/corelib/time/qmilankoviccalendar.cpp b/src/corelib/time/qmilankoviccalendar.cpp index 428b0169d4..3d848fb372 100644 --- a/src/corelib/time/qmilankoviccalendar.cpp +++ b/src/corelib/time/qmilankoviccalendar.cpp @@ -55,8 +55,9 @@ bool QMilankovicCalendar::isLeapYear(int year) const ++year; if (qMod<4>(year)) return false; - if (qMod<100>(year) == 0) { - const qint16 century = qMod<9>(qDiv<100>(year)); + const auto yeardm = qDivMod<100>(year); + if (yeardm.remainder == 0) { + const qint16 century = qMod<9>(yeardm.quotient); if (century != 2 && century != 6) return false; } @@ -72,11 +73,9 @@ bool QMilankovicCalendar::dateToJulianDay(int year, int month, int day, qint64 * ++year; const qint16 c0 = month < 3 ? -1 : 0; const qint16 x1 = month - 12 * c0 - 3; - const qint16 x4 = year + c0; - const qint16 x3 = qDiv<100>(x4); - const qint16 x2 = qMod<100>(x4); - *jd = qDiv<9>(328718 * x3 + 6) - + qDiv<100>(36525 * x2) + const auto x4dm = qDivMod<100>(year + c0); + *jd = qDiv<9>(328718 * x4dm.quotient + 6) + + qDiv<100>(36525 * x4dm.remainder) + qDiv<5>(153 * x1 + 2) + day + 1721119; return true; @@ -84,16 +83,13 @@ bool QMilankovicCalendar::dateToJulianDay(int year, int month, int day, qint64 * QCalendar::YearMonthDay QMilankovicCalendar::julianDayToDate(qint64 jd) const { - const qint64 k3 = 9 * (jd - 1721120) + 2; - const qint64 x3 = qDiv<328718>(k3); - const qint64 k2 = 100 * qDiv<9>(qMod<328718>(k3)) + 99; - const qint64 k1 = qDiv<100>(qMod<36525>(k2)) * 5 + 2; - const qint64 x2 = qDiv<36525>(k2); - const qint64 x1 = qDiv<153>(5 * qDiv<100>(qMod<36525>(k2)) + 2); - const qint64 c0 = qDiv<12>(x1 + 2); - const int y = 100 * x3 + x2 + c0; - const int month = x1 - 12 * c0 + 3; - const int day = qDiv<5>(qMod<153>(k1)) + 1; + const auto k3dm = qDivMod<328718>(9 * (jd - 1721120) + 2); + const auto k2dm = qDivMod<36525>(100 * qDiv<9>(k3dm.remainder) + 99); + const auto k1dm = qDivMod<153>(qDiv<100>(k2dm.remainder) * 5 + 2); + const auto c0dm = qDivMod<12>(k1dm.quotient + 2); + const int y = 100 * k3dm.quotient + k2dm.quotient + c0dm.quotient; + const int month = c0dm.remainder + 1; + const int day = qDiv<5>(k1dm.remainder) + 1; return QCalendar::YearMonthDay(y > 0 ? y : y - 1, month, day); } |