diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 59da4cb730..55c9f120a1 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -63,9 +63,9 @@ static inline QDate fixedDate(QCalendar::YearMonthDay parts) { if (parts.year) { parts.day = qMin(parts.day, QGregorianCalendar::monthLength(parts.month, parts.year)); - qint64 jd; - if (QGregorianCalendar::julianFromParts(parts.year, parts.month, parts.day, &jd)) - return QDate::fromJulianDay(jd); + const auto jd = QGregorianCalendar::julianFromParts(parts.year, parts.month, parts.day); + if (jd) + return QDate::fromJulianDay(*jd); } return QDate(); } @@ -437,9 +437,7 @@ QDate::QDate(int y, int m, int d) { static_assert(QDate::maxJd() == JulianDayMax); static_assert(QDate::minJd() == JulianDayMin); - - if (!QGregorianCalendar::julianFromParts(y, m, d, &jd)) - jd = nullJd(); + jd = QGregorianCalendar::julianFromParts(y, m, d).value_or(nullJd()); } QDate::QDate(int y, int m, int d, QCalendar cal) @@ -698,9 +696,8 @@ int QDate::dayOfYear(QCalendar cal) const int QDate::dayOfYear() const { if (isValid()) { - qint64 first; - if (QGregorianCalendar::julianFromParts(year(), 1, 1, &first)) - return jd - first + 1; + if (const auto first = QGregorianCalendar::julianFromParts(year(), 1, 1)) + return jd - *first + 1; } return 0; } @@ -1303,11 +1300,9 @@ QString QDate::toString(QStringView format, QCalendar cal) const */ bool QDate::setDate(int year, int month, int day) { - if (QGregorianCalendar::julianFromParts(year, month, day, &jd)) - return true; - - jd = nullJd(); - return false; + const auto maybe = QGregorianCalendar::julianFromParts(year, month, day); + jd = maybe.value_or(nullJd()); + return bool(maybe); } /*! @@ -2698,10 +2693,11 @@ QDateTimePrivate::ZoneState QDateTimePrivate::expressUtcAsLocal(qint64 utcMSecs) // dates might be right, and adjust by the number of days that was off: const qint64 jd = msecsToJulianDay(utcMSecs); const auto ymd = QGregorianCalendar::partsFromJulian(jd); - qint64 fakeJd, diffMillis, fakeUtc; - if (Q_UNLIKELY(!QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year), - ymd.month, ymd.day, &fakeJd) - || mul_overflow(jd - fakeJd, std::integral_constant(), + qint64 diffMillis, fakeUtc; + const auto fakeJd = QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year), + ymd.month, ymd.day); + if (Q_UNLIKELY(!fakeJd + || mul_overflow(jd - *fakeJd, std::integral_constant(), &diffMillis) || sub_overflow(utcMSecs, diffMillis, &fakeUtc))) { return result; @@ -2724,11 +2720,11 @@ static auto millisToWithinRange(qint64 millis) qint64 shifted = 0; bool good = false; } result; - qint64 jd = msecsToJulianDay(millis), fakeJd; + qint64 jd = msecsToJulianDay(millis); auto ymd = QGregorianCalendar::partsFromJulian(jd); - result.good = QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year), - ymd.month, ymd.day, &fakeJd) - && !daysAndMillisOverflow(fakeJd - jd, millis, &result.shifted); + const auto fakeJd = QGregorianCalendar::julianFromParts(systemTimeYearMatching(ymd.year), + ymd.month, ymd.day); + result.good = fakeJd && !daysAndMillisOverflow(*fakeJd - jd, millis, &result.shifted); return result; } diff --git a/src/corelib/time/qgregoriancalendar.cpp b/src/corelib/time/qgregoriancalendar.cpp index 1a4d3e5569..7db32e4cad 100644 --- a/src/corelib/time/qgregoriancalendar.cpp +++ b/src/corelib/time/qgregoriancalendar.cpp @@ -98,7 +98,10 @@ int QGregorianCalendar::weekDayOfJulian(qint64 jd) bool QGregorianCalendar::dateToJulianDay(int year, int month, int day, qint64 *jd) const { - return julianFromParts(year, month, day, jd); + const auto maybe = julianFromParts(year, month, day); + if (maybe) + *jd = *maybe; + return bool(maybe); } QCalendar::YearMonthDay QGregorianCalendar::julianDayToDate(qint64 jd) const @@ -175,17 +178,15 @@ constexpr qint64 BaseJd = LeapDayGregorian1Bce; // Every four centures there are 97 leap years: constexpr unsigned FourCenturies = 400 * 365 + 97; -bool QGregorianCalendar::julianFromParts(int year, int month, int day, qint64 *jd) +std::optional QGregorianCalendar::julianFromParts(int year, int month, int day) { - Q_ASSERT(jd); if (!validParts(year, month, day)) - return false; + return std::nullopt; const auto yearDays = yearMonthToYearDays(year, month); const qint64 y = yearDays.year; const qint64 fromYear = 365 * y + qDiv<4>(y) - qDiv<100>(y) + qDiv<400>(y); - *jd = fromYear + yearDays.days + day + BaseJd ; - return true; + return fromYear + yearDays.days + day + BaseJd; } QCalendar::YearMonthDay QGregorianCalendar::partsFromJulian(qint64 jd) diff --git a/src/corelib/time/qgregoriancalendar_p.h b/src/corelib/time/qgregoriancalendar_p.h index dc40937577..ed950ecf49 100644 --- a/src/corelib/time/qgregoriancalendar_p.h +++ b/src/corelib/time/qgregoriancalendar_p.h @@ -17,6 +17,8 @@ #include "qromancalendar_p.h" +#include + QT_BEGIN_NAMESPACE class Q_CORE_EXPORT QGregorianCalendar : public QRomanCalendar @@ -45,7 +47,7 @@ public: static int monthLength(int month, int year); static bool validParts(int year, int month, int day); static QCalendar::YearMonthDay partsFromJulian(qint64 jd); - static bool julianFromParts(int year, int month, int day, qint64 *jd); + static std::optional julianFromParts(int year, int month, int day); // Used internally: static int yearStartWeekDay(int year); static int yearSharingWeekDays(QDate date); diff --git a/src/corelib/time/qlocaltime.cpp b/src/corelib/time/qlocaltime.cpp index 4684aa7141..145da91723 100644 --- a/src/corelib/time/qlocaltime.cpp +++ b/src/corelib/time/qlocaltime.cpp @@ -167,10 +167,8 @@ struct tm timeToTm(qint64 localDay, int secs, QDateTimePrivate::DaylightStatus d inline std::optional tmToJd(const struct tm &date) { - qint64 jd; return QGregorianCalendar::julianFromParts(qYearFromTmYear(date.tm_year), - date.tm_mon + 1, date.tm_mday, &jd) - ? std::optional(jd) : std::nullopt; + date.tm_mon + 1, date.tm_mday); } #define IC(N) std::integral_constant() @@ -374,9 +372,7 @@ QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::Dayligh SystemMillisRange computeSystemMillisRange() { // Assert this here, as this is called just once, in a static initialization. - [[maybe_unused]] qint64 epochJd; - Q_ASSERT(QGregorianCalendar::julianFromParts(1970, 1, 1, &epochJd) - && epochJd == JULIAN_DAY_FOR_EPOCH); + Q_ASSERT(QGregorianCalendar::julianFromParts(1970, 1, 1) == JULIAN_DAY_FOR_EPOCH); constexpr qint64 TIME_T_MAX = std::numeric_limits::max(); using Bounds = std::numeric_limits; diff --git a/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp b/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp index acc190c92e..4eebce6d80 100644 --- a/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp +++ b/tests/auto/corelib/time/qcalendar/tst_qcalendar.cpp @@ -368,13 +368,12 @@ void tst_QCalendar::gregory() // dateToJulianDay() and weekDayOfJulian(): if (!year) // No year zero. continue; - qint64 first, last; - QVERIFY2(QGregorianCalendar::julianFromParts(year, 1, 1, &first), - "Only year zero should lack a first day"); + const auto first = QGregorianCalendar::julianFromParts(year, 1, 1); + QVERIFY2(first, "Only year zero should lack a first day"); QCOMPARE(QGregorianCalendar::yearStartWeekDay(year), - QGregorianCalendar::weekDayOfJulian(first)); - QVERIFY2(QGregorianCalendar::julianFromParts(year, 12, 31, &last), - "Only year zero should lack a last day"); + QGregorianCalendar::weekDayOfJulian(*first)); + const auto last = QGregorianCalendar::julianFromParts(year, 12, 31); + QVERIFY2(last, "Only year zero should lack a last day"); const int lastTwo = (year + (year < 0 ? 1 : 0)) % 100 + (year < -1 ? 100 : 0); const QDate probe(year, lastTwo && lastTwo <= 12 ? lastTwo : 8, @@ -392,13 +391,14 @@ void tst_QCalendar::gregory() if (year > 0 && lastTwo > 31) QCOMPARE(match % 100, lastTwo); // Its first and last days of the year match those of year: - qint64 day; - QVERIFY(QGregorianCalendar::julianFromParts(match, 1, 1, &day)); - QCOMPARE(QGregorianCalendar::weekDayOfJulian(day), - QGregorianCalendar::weekDayOfJulian(first)); - QVERIFY(QGregorianCalendar::julianFromParts(match, 12, 31, &day)); - QCOMPARE(QGregorianCalendar::weekDayOfJulian(day), - QGregorianCalendar::weekDayOfJulian(last)); + auto day = QGregorianCalendar::julianFromParts(match, 1, 1); + QVERIFY(day); + QCOMPARE(QGregorianCalendar::weekDayOfJulian(*day), + QGregorianCalendar::weekDayOfJulian(*first)); + day = QGregorianCalendar::julianFromParts(match, 12, 31); + QVERIFY(day); + QCOMPARE(QGregorianCalendar::weekDayOfJulian(*day), + QGregorianCalendar::weekDayOfJulian(*last)); } } }