diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 2e4757b5255..248fd1d5cef 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -4608,6 +4608,10 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int of */ QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec, int offsetSeconds) { + constexpr qint64 maxSeconds = std::numeric_limits::max() / 1000; + constexpr qint64 minSeconds = std::numeric_limits::min() / 1000; + if (secs > maxSeconds || secs < minSeconds) + return QDateTime(); // Would {und,ov}erflow return fromMSecsSinceEpoch(secs * 1000, spec, offsetSeconds); } @@ -4641,6 +4645,10 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone */ QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone) { + constexpr qint64 maxSeconds = std::numeric_limits::max() / 1000; + constexpr qint64 minSeconds = std::numeric_limits::min() / 1000; + if (secs > maxSeconds || secs < minSeconds) + return QDateTime(); // Would {und,ov}erflow return fromMSecsSinceEpoch(secs * 1000, timeZone); } #endif diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index 2e454605441..bf845085227 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -73,6 +73,7 @@ private slots: void setSecsSinceEpoch(); void setMSecsSinceEpoch_data(); void setMSecsSinceEpoch(); + void fromSecsSinceEpoch(); void fromMSecsSinceEpoch_data(); void fromMSecsSinceEpoch(); void toString_isoDate_data(); @@ -790,6 +791,36 @@ void tst_QDateTime::fromMSecsSinceEpoch() QCOMPARE(dtOffset, reference.addMSecs(msecs)); } +void tst_QDateTime::fromSecsSinceEpoch() +{ + const qint64 maxSeconds = std::numeric_limits::max() / 1000; + + QVERIFY(QDateTime::fromSecsSinceEpoch(maxSeconds).isValid()); + QVERIFY(!QDateTime::fromSecsSinceEpoch(maxSeconds + 1).isValid()); + QVERIFY(QDateTime::fromSecsSinceEpoch(-maxSeconds).isValid()); + QVERIFY(!QDateTime::fromSecsSinceEpoch(-maxSeconds - 1).isValid()); + + QVERIFY(QDateTime::fromSecsSinceEpoch(maxSeconds, Qt::UTC).isValid()); + QVERIFY(!QDateTime::fromSecsSinceEpoch(maxSeconds + 1, Qt::UTC).isValid()); + QVERIFY(QDateTime::fromSecsSinceEpoch(-maxSeconds, Qt::UTC).isValid()); + QVERIFY(!QDateTime::fromSecsSinceEpoch(-maxSeconds - 1, Qt::UTC).isValid()); + + // Use an offset for which .toUTC()'s return would flip the validity: + QVERIFY(QDateTime::fromSecsSinceEpoch(maxSeconds, Qt::OffsetFromUTC, 7200).isValid()); + QVERIFY(!QDateTime::fromSecsSinceEpoch(maxSeconds + 1, Qt::OffsetFromUTC, -7200).isValid()); + QVERIFY(QDateTime::fromSecsSinceEpoch(-maxSeconds, Qt::OffsetFromUTC, -7200).isValid()); + QVERIFY(!QDateTime::fromSecsSinceEpoch(-maxSeconds - 1, Qt::OffsetFromUTC, 7200).isValid()); + +#if QT_CONFIG(timezone) + // As for offset, use zones each side of UTC: + const QTimeZone west("UTC-02:00"), east("UTC+02:00"); + QVERIFY(QDateTime::fromSecsSinceEpoch(maxSeconds, east).isValid()); + QVERIFY(!QDateTime::fromSecsSinceEpoch(maxSeconds + 1, west).isValid()); + QVERIFY(QDateTime::fromSecsSinceEpoch(-maxSeconds, west).isValid()); + QVERIFY(!QDateTime::fromSecsSinceEpoch(-maxSeconds - 1, east).isValid()); +#endif // timezone +} + void tst_QDateTime::toString_isoDate_data() { QTest::addColumn("datetime");