Допустимый диапазон для QDateTime:: fromMSecsSinceEpoch


Я обнаружил странное поведение в QDateTime Qt 4.8 относительно fromMSecsSinceEpoch. Следующий код не дает ожидаемого результата:

assert(
    QDateTime::fromMSecsSinceEpoch(
        std::numeric_limits<qint64>::max()
    ).isValid() == true
);
assert(
    QDateTime::fromMSecsSinceEpoch(
        std::numeric_limits<qint64>::max()
    ).toMSecsSinceEpoch() == std::numeric_limits<qint64>::max()
);
В то время как первое утверждение истинно, второе терпит неудачу. Возвращаемый результат Qt равен -210866773624193. В doc для QDateTime::fromMSecsSinceEpoch(qint64 msecs) ясно говорится:

Существуют возможные значения для мсек, которые лежат за пределами допустимого диапазона QDateTime, как отрицательные, так и положительные. Поведение этой функции не определено для тех, кто ценности.

Однако нет никакого явного утверждения о допустимом диапазоне.

Я нашел этот отчет об ошибке Qt о проблеме, касающейся часовых поясов в бета-версии Qt 5.5.1, 5.6.0 и 5.7.0. Я не уверен, что это похожая ошибка, или если значение, которое я предоставил QDateTime::fromMSecsSinceEpoch(qint64 msecs), просто недопустимо.

Каково (или, скорее, должно быть) максимальное значение, которое может быть передано этой функции и дает правильное поведение?

1 2

1 ответ:

std::numeric_limits<qint64>::max() ms выходы 9 223 372 036 854 775 807 ms, или 9 223 372 036 854 775 s, или 2 562 047 788 015 hours, или 106 751 991 167 days, или 292 471 208 years: это далеко за пределы 11 миллионов лет в допустимом диапазоне QDateTime.

Изdoc , действительные даты начинаются со 2 января 4713 года до н. э. и идут до переполнения QDate::toJulianDay(): 2^31 days (максимальное значение для целого числа со знаком) дает почти 5 000 000 years. Это 185 542 587 187 200 000 ms (от 2 января 4713 года до н. э., а не от эпохи), "немного" больше 2^57.

Редактировать:

После обсуждения в комментариях вы проверили источники Qt4. 8 и обнаружил, что fromMSecsSinceEpoch() использует QDate(1970, 1, 1).addDays(ddays) внутренне, где число дней вычисляется непосредственно из параметра msecs.

Так как ddays имеет здесь тип int, это будет переполнение для значений больше, чем 2^31.