Ruby 1.8.7でRails 3.2.1とJbuilderを使用して単純なJSON APIを構築しています(1.9.xは役に立ちますが、ホスティングプロバイダは1.8.7しかありません)。 APIの消費者は、フロートとしてタイムスタンプを期待しRails:JSONの#to_f精度?
ので、私は現在、ちょうど時間に簡単なto_f
属性をやっている:
json.updated_at record.updated_at.to_f #=> 1328242368.02242
しかしto_f
は、精度の損失を被ります。これは、クライアントが特定の時点以降に変更されたレコードを要求するときに、SQLクエリーがクライアントが参照用に使用するのと同じレコードを検出するときに、いくつかの問題を引き起こします。私。上記の例よりも新しいレコードを検索しようとすると、実際の値がupdated_at
であるため、SQLクエリ(例:updated_at > Time.at(1328242368.02242)
)は同じレコードを返します。
実際にはrecord.updated_at.useC#=> 22425
または0.022425
秒です。特別な小数点に注意してください。
タイムスタンプは、最適な小数点以下1桁で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浮動小数点はそれを扱うことができないので、それはJS互換性(したがってJSON仕様)を破ることになります。だから、おそらく私は
時刻を文字列として出力できますか? "#{updated_at.to_i}。#{updated_at.usec}" '? (まあ、必要に応じて 'usec'に先行する0を加えてください。) – millimoose
はい、いいえ。私は文字列を出力していた場合、私はそれのようなものをたくさんすることができました。しかし、私はフロートを出力する必要があります。そして、文字列を作成してから 'to_f'を実行すると、私が始めたところに戻ります:精度損失。 – Flambino
浮動小数点数の代わりにBigDecimalを出力できますか? JSONライブラリは、それらを数値として扱うことができます。 – millimoose