Rails ActiveRecord Timestamp in Epoch 而不是 DateTime 格式

Posted

技术标签:

【中文标题】Rails ActiveRecord Timestamp in Epoch 而不是 DateTime 格式【英文标题】:Rails ActiveRecord Timestamp in Epoch instead of DateTime Format 【发布时间】:2016-10-05 23:26:58 【问题描述】:

需要以 Epoch 而不是 DateTime 格式存储 created_at 和 updated_at 时间戳。有没有办法改变默认行为,同时让 ORM 来维护时间戳。

当我使用 Rails Generator 生成模型时

class CreateTenants < ActiveRecord::Migration[5.0]
  def change
    create_table :tenants do |t|
      t.string :tenant_name
      t.string :tenant_owner_name
      t.string :tenant_address
      t.string :tenant_email
      t.integer :pincode

      t.timestamps
    end
  end
end

不是转换为 DateTime 的时间戳。

create_table "tenants", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string   "tenant_name"
    t.string   "tenant_owner_name"
    t.string   "tenant_address"
    t.string   "tenant_email"
    t.integer  "pincode"
    t.datetime "created_at",        null: false
    t.datetime "updated_at",        null: false
  end

我知道我可以直接创建两列,并在每次添加/更改记录时手动更改 created_at 和 updated_at 字段,但这将是应用程序中引入的大量错误代码冗余代码。

我需要以某种方式以纪元格式(自 1970 年以来的时间长)而不是 DateTime 存储时间戳。

谢谢

【问题讨论】:

您是否尝试在架构中将 created_atupdated_at 列定义为 timestamp 列? 是的。但默认情况下它采用 sql 日期时间格式。但我想将其存储为 Epoch 而不是 DateTime 对不起,也许我不明白你所说的 Epoch 是什么意思。我以为您的意思是将列存储为自 1970 年以来的秒数,我猜,如果您将列定义为 timestamp 列,那么它可能会起作用。您能否详细说明您想要实现的目标? 更新了我的问题 【参考方案1】:

你没有指定使用的数据库,所以我在这里假设 mysql。事实证明,Rails 支持时间戳的所有日期/时间列变体:DATETIMEDATETIMETIMESTAMP 甚至 INTEGER。有关这些类型之间差异的更多信息,请参阅MySQL docs,有关 Rails 如何理解它们的信息,请参阅this answer。

1) TIMESTAMP 时间戳列

如果您想将时间戳存储在TIMESTAMP 类型列中,请在迁移中尝试以下技巧(注意'timestamp ' 中的空格,它是needed 否则Rails 将始终创建datetime 的列改为 - timestamp 只是 Rails 中 datetime 的别名):

create_table :tenants do |t|
  # ...

  #t.timestamps (remove the default timestamps definition) 
  t.column :created_at, 'timestamp ', null: false
  t.column :updated_at, 'timestamp ', null: false
end

处理记录时,时间戳将显示为通常的日期时间,但将在数据库中存储为TIMESTAMPs,从而为每条记录节省几个字节:

Tenant.create!
# => SQL (0.1ms)  INSERT INTO `tenants` (`created_at`, `updated_at`) VALUES ('2016-06-08 08:45:20', '2016-06-08 08:45:20')
=> #<Tenant id: 1, tenant_name: nil, tenant_owner_name: nil, tenant_address: nil, tenant_email: nil, pincode: nil, created_at: "2016-06-08 08:45:20", updated_at: "2016-06-08 08:45:20">

当然,您始终可以使用to_i 方法将日期时间转换为纪元以来的秒数:

Tenant.last.created_at.to_i
# => 1465375595

2) INTEGER 时间戳列

如果您确实想将时间戳存储为自纪元以来的秒数(1970),只需将时间戳列定义为INTEGER 类型列:

create_table :tenants do |t|
  # ...

  #t.timestamps (remove the default timestamps definition)
  t.integer :created_at, null: false
  t.integer :updated_at, null: false
end

那么,记录中的时间戳在 Rails 中也显示为整数:

Tenant.create!
# => SQL (0.2ms)  INSERT INTO `tenants` (`created_at`, `updated_at`) VALUES (1465375595, 1465375595)
# => #<Tenant id: 1, tenant_name: nil, tenant_owner_name: nil, tenant_address: nil, tenant_email: nil, pincode: nil, created_at: 1465375595, updated_at: 1465375595>

【讨论】:

以上是关于Rails ActiveRecord Timestamp in Epoch 而不是 DateTime 格式的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3 包括翻译 globalize3 activerecord

脱离Rails单独使用ActiveRecord的几点需知

没有Rails的ActiveRecord

Rails/Arel:选择所有记录作为 ActiveRecord::Relation

为啥 Rails 5 使用 ApplicationRecord 而不是 ActiveRecord::Base?

Rails 扩展 ActiveRecord::Base