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

Rails API vs NSDate - Precision issues when comparing dates

我的 iOS 应用程序使用 rails API 输出 JSON 格式的日期,精度为 3 位微秒,如下例所示。这是为对应实体解析保存的,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 上加半秒来解决这个问题,但这显然是一个 hack。

任何人都可以推荐在这种情况下最合适的行动方案吗?

TIA

在这种情况下,我认为最好的方法是将存储在数据库中并输出为 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 where support was added for Postgresql. If you are on MySQL, please note that only MySQL 5.6.4 and above 支持比秒更精确的 DATETIME。那不是你的问题,你已经说过你的数据库存储了 6 位精度的日期时间,但我认为这里值得注意。

我还可以想到其他方法,尽管 none 看起来比上述方法更好,但它们也可能值得注意:

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

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

一行代码即可实现:

ActiveSupport::JSON::Encoding.time_precision = 6

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

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