sigy
sigy

Reputation: 2500

Valid range for QDateTime::fromMSecsSinceEpoch

I discovered a strange behavior in QDateTime of Qt 4.8 regarding fromMSecsSinceEpoch. The following code does not produce the result I would expect:

assert(
    QDateTime::fromMSecsSinceEpoch(
        std::numeric_limits<qint64>::max()
    ).isValid() == true
);
assert(
    QDateTime::fromMSecsSinceEpoch(
        std::numeric_limits<qint64>::max()
    ).toMSecsSinceEpoch() == std::numeric_limits<qint64>::max()
);

While the first assertion is true, the second fails. The returned result from Qt is -210866773624193. The doc for QDateTime::fromMSecsSinceEpoch(qint64 msecs) clearly states:

There are possible values for msecs that lie outside the valid range of QDateTime, both negative and positive. The behavior of this function is undefined for those values.

However, there is no any explicit statement about the valid range.

I found this Qt bug report about an issue regarding timezones in Qt 5.5.1, 5.6.0 and 5.7.0 Beta. I am not sure wheter this is a similar bug, or if the value I provided to QDateTime::fromMSecsSinceEpoch(qint64 msecs) is simply invalid.

What is (or rather should be) the maximum value that can be passed to this function and yields correct behavior?

Upvotes: 2

Views: 1368

Answers (1)

rocambille
rocambille

Reputation: 15996

std::numeric_limits<qint64>::max() ms yields 9 223 372 036 854 775 807 ms, or 9 223 372 036 854 775 s, or 2 562 047 788 015 hours, or 106 751 991 167 days, or 292 471 208 years: that's far beyond the year 11 million in the valid range of QDateTime.

From the doc, valid dates start from January 2nd, 4713 BCE, and go until QDate::toJulianDay() overflow: 2^31 days (max value for signed integer) yields nearly 5 000 000 years. That's 185 542 587 187 200 000 ms (from January 2nd, 4713 BCE, not from Epoch), "little" more than 2^57.

EDIT:

After discussion in the comments, you checked Qt4.8 sources and found that fromMSecsSinceEpoch() uses QDate(1970, 1, 1).addDays(ddays) internally, where the number of days is calculated directly from the msecs parameter.

Since ddays is of type int here, this would overflow for values larger than 2^31.

Upvotes: 2

Related Questions