Rails API与NSDate - 比较日期时的精度问题

时间:2015-02-25 03:02:16

标签: ios ruby-on-rails ruby datetime nsdate

我的iOS应用程序使用rails API,输出具有3位微秒精度的JSON格式日期,如下例所示。这将被解析并保存为相应的实体,NSDate保留了预期的3位精度:

{ "updated_at": "2015-02-24T22:37:57.683Z" }

当我将此日期发回API以查询记录时,数据库中的updated_at字段似乎具有(至少)6位数的精度:

>> my_model.update_at.strftime('%Y-%m-%d %H:%M:%S.%N')
>> 2015-02-24 22:37:57.683977000

这意味着每次我查询

>> ios_date = json_hash["updated_at"]
>> Model.where("updated_at > ?", ios_date) 

我在应用的数据库中已经存在一条记录。

我知道我可以在ios_date添加半秒来解决此问题,但这显然是一个黑客攻击。

在这种情况下,有人可以推荐什么是最合适的行动方案吗?

TIA

2 个答案:

答案 0 :(得分:1)

在这种情况下,我认为最好的方法是存储在数据库中并输出为JSON 完全相同的东西,以避免任何转换或舍入问题的需要。我假设你想要保留3位微秒的精确日期,我只是将你的数据库配置为以这种精度存储日期。

您可以使用迁移来修改:created_at和:updated_at字段的精度,如下所示:

class MicrosecondsMigration < ActiveRecord::Migration
  def up
    change_column :your_table, :created_at, :datetime, precision: 3
    change_column :your_table, :updated_at, :datetime, precision: 3
  end

  def down
    change_column :your_table, :created_at, :datetime
    change_column :your_table, :updated_at, :datetime
  end
end

我相信这将适用于主要数据库。 Check this commit at Rails为Postgresql添加了支持。如果您使用的是MySQL,请注意只有MySQL 5.6.4 and above支持DATETIME的精度高于一秒。这不是你的问题,你已经说过你的数据库存储了6位数的精确日期时间,但我认为这值得注意。

我可以想到其他方法,虽然没有一种看起来比上述方法更好,但它们也值得注意:

  • 使用某些SQL更改查询以从日期中删除多余的数字。我不建议走这条路:你需要在每个需要做的查询中考虑到这一点。越野车,打败AR的目的,看起来很难看。
  • 手动为您的ios_date添加几毫秒,感觉更加丑陋。
  • 当然,您始终可以更改JSON API以支持数据库处理的完整6位数精度。正如我之前所说,我认为这不是你的意图。

答案 1 :(得分:0)

即使更改created_at和updated_at的精度限制的选项是一个有效选项,我发现最干净/最“Railsy”的解决方案是获得to_json的输出以匹配数据库精度。

这可以通过一行代码来实现:

ActiveSupport::JSON::Encoding.time_precision = 6

实际上,这并没有真正解决问题,因为时间戳的基础存储类型是浮点数,因此某些时间比较仍然失败。

最后,根据@dgilperez在本页的回答,降低精确度是我的选择。