【问题标题】:Valid range for QDateTime::fromMSecsSinceEpochQDateTime::fromMSecsSinceEpoch 的有效范围
【发布时间】:2016-11-22 08:13:18
【问题描述】:

我在 Qt 4.8 的 QDateTime 中发现了一个关于 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 返回的结果是-210866773624193doc for QDateTime::fromMSecsSinceEpoch(qint64 msecs) 明确指出:

有可能的毫秒值位于 QDateTime 的有效范围之外,包括负值和正值。对于这些值,此函数的行为是未定义的。

但是,没有任何关于有效范围的明确声明。

我发现这个Qt bug report 是关于 Qt 5.5.1、5.6.0 和 5.7.0 Beta 中的时区问题。 我不确定这是否是一个类似的错误,或者我提供给QDateTime::fromMSecsSinceEpoch(qint64 msecs) 的值是否完全无效。

什么是(或更确切地说应该是)可以传递给此函数并产生正确行为的最大值?

【问题讨论】:

  • 有效日期的范围是从公元前 4713 年 1 月 2 日到公元 1100 万年的某个时间
  • 我读到了,但它没有给出确切的值
  • 文档没有给出确切的值,它在11'000'000 * 365 * 3600 * 1000附近的某个地方@
  • @Danh 不是11'000'000 * 365 * 24 * 3600 * 1000
  • @wasthishelpful 是的,忘记了

标签: c++ qt qt5


【解决方案1】:

std::numeric_limits&lt;qint64&gt;::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:这远远超过QDateTime 有效范围内的1100 万年。

the doc 开始,有效日期从公元前 4713 年 1 月 2 日开始,一直到 QDate::toJulianDay() 溢出:2^31 days(有符号整数的最大值)几乎产生 5 000 000 years。那是 185 542 587 187 200 000 ms(从公元前 4713 年 1 月 2 日开始,而不是从纪元开始),比 2^57 多“一点”。

编辑:

在cmets中讨论后,你查看了Qt4.8的源码,发现fromMSecsSinceEpoch()内部使用QDate(1970, 1, 1).addDays(ddays),其中天数是直接从msecs参数计算出来的。

由于此处ddays 的类型为int,因此对于大于2^31 的值会溢出。

【讨论】:

  • 我进行了二进制搜索,看起来传递给fromMSecsSinceEpoch() 的最大有效值是185542587187199999,它产生Fr。 UTC 时间 7 月 11 日 23:59:59 5881580,距离公元 1100 万年还很远。
  • 好的,这支持了我的二进制搜索结果。但是,它仍然不是文档所述的日期公元 1100 万年的某个时间。是不是文档有问题?
  • 看起来是这样。该文档在 Qt5 中有更改(请参阅here),因此我无法查看 Qt5 代码,我必须找到完整的答案。如果您想/需要更进一步,您将不得不查看 Qt4.8 的来源(请随时在此处分享结果,以便我可以更新我的答案;))
  • 我应该早点这样做...fromMSecsSinceEpoch() 在内部使用QDate(1970, 1, 1).addDays(ddays),其中天数直接从msecs 参数计算。由于ddaysint 类型,因此对于大于 2^31 的值会溢出。所以你的计算是正确的,我认为这是 Qt 4.8 中的一个错误
猜你喜欢
  • 1970-01-01
  • 2020-09-16
  • 2012-01-11
  • 1970-01-01
  • 2018-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
相关资源
最近更新 更多