【问题标题】:Rails:How to create a time column with timezone on postgresRails:如何在 postgres 上创建带有时区的时间列
【发布时间】:2013-10-13 00:34:33
【问题描述】:

我有一个在 postgres 数据库上运行的 rails 应用程序。我有一个名为 UserTimings 的模型,其中有两个字段 from_time 和 to_time。

t.time     "from_time"
t.time     "to_time"

我预计时间将以带有时区信息的完整 UTC 格式存储。过了一会儿,我意识到数据库有这种SQL查询来创建表。

from_time time without time zone,
to_time time without time zone,

我不想要这个。我想用时区存储。我想要 UTC 时间的 +0530 东西,尽管 rails 应用程序已配置为处理它,但我没有得到它。请告诉我如何编写迁移以强制数据库使用时区。

谢谢。

【问题讨论】:

  • railscasts.com/episodes/106-time-zones-in-rails-2-1 这个 railscast 说我们的记录中必须有一个 time_zone:string 列。但是 Postgres 已经支持时区了!如何使用该功能?
  • 我想要时间和时区。如何在 Rails 迁移中专门为 postgres 指定时间列和时区?

标签: ruby-on-rails postgresql timezone utc


【解决方案1】:

不确定这是您想要的,但这对我有用:

add_column :table, :from_time, :timetz
add_column :table, :to_time, :timetz

但rails似乎无法识别timetz类型,它将被视为String。为了解决这个问题,我将 timetz 注册为时间。

ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
  def initialize_type_map_with_postgres_oids mapping
    initialize_type_map_without_postgres_oids mapping
    register_class_with_limit mapping, 'timetz',
                              ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::OID::Time
  end

  alias_method_chain :initialize_type_map, :postgres_oids
end

顺便说一句,我的环境是 rails-4.2

【讨论】:

    【解决方案2】:

    迁移完全按照您的意愿进行

    class CreatePeppers < ActiveRecord::Migration
      def change
        create_table :peppers do |t|
          t.column :runs, 'timestamp with time zone'
          t.column :stops, 'time with time zone'
        end
      end
    end
    

    类型供您选择。您可以在此处编写 postgresql 支持的任何类型。但是转换为类型可能会出现问题,rails 可以理解。

    【讨论】:

    • 另外,该链接在处理时间时可能会有所帮助。 api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html
    • 幸运的是,最新的 SQLite 似乎也支持 'timestamp with time zone'
    • 警告很重要——你可以在数据库中创建一个“带时区的时间”列,但是当你读回它时,你会得到类似unknown OID 1266: failed to recognize type of '&lt;column_name&gt;'. It will be treated as String的东西,并且值将是字符串,例如"17:15:00-07".
    【解决方案3】:

    您似乎对这里的两个不同的事情感到困惑 - 都是常见的错误,几乎每个人都至少犯过一个。

    首先,“带有时区信息的 UTC 格式”没有指定时间。它指定了时间和地点。

    其次,PostgreSQL 的“带有时区的时间戳”实际上并不存储时区。它存储一个 UTC 时间戳,但它接受一个时区。更好的名称选择是“绝对时间”。您可以直接比较其中两个值。

    没有时区的时间戳实际上不会给你一个时间,除非你也有一个地方。除非您知道各自所在的时区,否则无法比较其中两个。

    听起来你想要的一个没有时区和单独时区的时间戳。这样你就可以说“伦敦时间周二下午 2 点”。

    【讨论】:

    • 那要么你没看懂我写的内容,要么你的问题描述有误。
    • 我不知道定义或区别是什么。我被要求存储整个事情,时间和时区。我需要迁移来做到这一点。有没有办法使用带有时区选项的 postgres 时间列?如果是的话教我怎么做。
    • 不,你不能。那不是它的作用。恐怕我不知道如何向您更清楚地解释细节。
    猜你喜欢
    • 2011-12-27
    • 2019-11-08
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多