【问题标题】:Millisecond timestamp => ISO date is off by 1 millisecond毫秒时间戳 => ISO 日期相差 1 毫秒
【发布时间】:2020-04-13 06:39:57
【问题描述】:

我有一个以毫秒为单位的时间戳,我想将其转换为 UTC 格式的 ISO 日期字符串:

require 'time'

timestamp = 1534442471123

puts Time.at(timestamp / 1000.0).utc.strftime('%FT%T.%3NZ')

哪个输出:

2018-08-16T18:01:11.122Z

为什么会延迟 1 毫秒(...122Z,而不是 ...123Z)?

这是因为浮点数内存表示问题吗?

【问题讨论】:

  • usual definition of floating point 表示以 2 为底的指数。因此,您不能可靠地除以 1000。如果您只是计算一些 x/1000.0 并打印结果,您可能不会注意到错误,因为它在舍入/格式化期间得到补偿。如果您需要精确的结果,请避免使用浮点运算。

标签: ruby time


【解决方案1】:

虽然您已经意识到 Float 的不准确性在这里发挥了作用,但它最终是 %N 转换说明符的“错误”,它想要阻止您进入未来。 From the documentation:

  The digits under the specified length are truncated to avoid
  carry up.

在这种情况下,其他转化(例如 sprintf 和 '%.3f')会被四舍五入。所以你的Time对象的毫秒实际上不是123而是122.9???,因为%3N变成122。精确处理(亚)秒Time 支持整数和有理数:

Time.at(*timestamp.divmod(1000), :millisecond, in: 'utc')
# or
Time.at(Rational(timestamp, 1000), in: 'utc')
Time.at(timestamp / 1000r, in: 'utc')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-12
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    相关资源
    最近更新 更多