Ruby Rails:JSON中的精确时间?

Ruby Rails:JSON中的精确时间?,ruby,ruby-on-rails-3,json,floating-point,Ruby,Ruby On Rails 3,Json,Floating Point,我正在使用Rails 3.2.1和Ruby 1.8.7构建一个简单的JSON API(1.9.x可能对我有所帮助,但我的托管提供商只有1.8.7) 由于API使用者希望时间戳是浮动的,所以我目前正在对时间属性执行一个简单的操作: json.updated_at record.updated_at.to_f #=> 1328242368.02242 但是to_f会导致精度损失。当客户端请求自给定时间点以来已修改的记录时,这会导致一些问题,因为SQL查询会找到客户端用于引用的相同记录。也就是

我正在使用Rails 3.2.1和Ruby 1.8.7构建一个简单的JSON API(1.9.x可能对我有所帮助,但我的托管提供商只有1.8.7)

由于API使用者希望时间戳是浮动的,所以我目前正在对时间属性执行一个简单的
操作:

json.updated_at record.updated_at.to_f #=> 1328242368.02242
但是
to_f
会导致精度损失。当客户端请求自给定时间点以来已修改的记录时,这会导致一些问题,因为SQL查询会找到客户端用于引用的相同记录。也就是说,当试图查找比上述示例更“新”的记录时,SQL查询(例如,
updated\u at>Time.at(1328242368.02242)
)返回相同的记录,因为
updated\u at
的实际值比给定的时间戳更精确、更大

事实上,
record.updated_at.usec#=>22425
0.022425
秒。注意额外的小数点

因此,最佳情况下,时间戳应该用一个额外的小数点JSON化,例如1328242368.022425,但我找不到实现这一点的方法

updated_at.to_i #=> 1328242368       # seconds
updated_at.usec #=> 22425            # microseconds
updated_at.to_f #=> 1328242368.02242 # precision loss

# Hacking around `to_f` doesn't help
decimals = updated_at.usec / 1000000.0 #=> 0.022425         # yay, decimals!
updated_at.to_i + decimals             #=> 1328242368.02242 # dammit!
我到处寻找设置默认浮点精度的方法,但是我被难住了。有什么想法吗


编辑:我应该补充一点,API使用者没有运行JavaScript,因此浮点可以具有更高的精度。添加另一个数字(十进制或其他数字)会破坏JS兼容性(从而破坏JSON规范),因为我相信JS float无法处理这个问题。所以也许我需要一个完全不同的方法

在评论中经过深思熟虑后,最好的选择似乎是monkeypatching
ActiveSupport::JSON
,以使其处理
BigDecimal
s与
Numeric
s相同:

class BigDecimal
  def as_json(options = nil) self end #:nodoc:
  def encode_json(encoder) to_s end #:nodoc:
end

这推翻了Rails团队的决定,即防止序列化的
BigDecimal
s在不支持十进制数的JSON反序列化程序中被解析为浮点数(并失去精度)。

能否将时间作为字符串输出:
“{updated_at.to_i}.{updated_at.usec}”
?(好吧,根据需要将前导零添加到
usec
)是和否。如果我输出字符串,我可以做很多类似的事情。但我需要输出一个浮点。如果我生成一个字符串,然后对它运行
到_f
,我回到了开始的地方:精度损失。你能输出大小数而不是浮点数吗?JSON库可能可以将它们视为数字。关闭但不关闭
BigDecimal
将JSON'd作为字符串获取(尽管具有适当的精度)。如果I
to_f
a
BigDecimal
实例,它将再次导致精度损失。。。我可能需要找到一种附加“原始”JSON的方法,这样我就可以使用
BigDecimal
来获取字符串,并在不加引号的情况下输出它。似乎有点骇人听闻,但是…
BigDecimal
仅作为
to_s
回退支持是值得针对JSON库报告一个bug的。这是一个数字,应该编码为一。