Rails中无限时间范围的问题

Yar*_*rin 3 postgresql activerecord ruby-on-rails

在同时具有时间范围(Postgres type tsrange)和日期范围(Postgres type daterange)字段的表上...

保存然后从数据库中检索无限/无限时间范围会导致错误:

object.a_time_range = Time.now.utc..DateTime::Infinity.new
object.save!
object.reload
Run Code Online (Sandbox Code Playgroud)

=> ArgumentError:范围的值错误

但是,对日期范围执行相同操作会很好:

object.a_date_range = Date.today..Date::Infinity.new
object.save!
object.reload
Run Code Online (Sandbox Code Playgroud)

有没有办法在Rails中使用无限的时间范围?

红宝石:2.3.0,导轨:4.2.6

(另请参见ruby-是否有一种表达“无限时间”的方法-堆栈溢出

Ver*_*ics 5

您不能将Infinity作为时间范围的一部分存储在Rails中。我相信这是因为将Infinity从字符串PSQL oid中拉出时将作为字符串值插入并解释为浮点数。因此,Date-> Float中的任何日期范围都不可行。但是,您可以使用伪(自现在起的一百万年)日期创建自己的范围,也可以只使用两个单独的日期字段并在模型中对其进行适当解释。开始日期,结束日期。

在Rails 4.2+中,您可以在日期时间类型内存储一个Float :: INFINITY值。例。

User.first.update(begin_date: DateTime.now, end_date: 'infinity')
User.first.end_date # => Infinity
Run Code Online (Sandbox Code Playgroud)

但是,这end_date将不是一个有效的日期。您只是将字符串存储在数据库中,并且在调用它时会提取一个浮点数

这是处理该问题的实际(Rails 4.2)代码:

module ActiveRecord
  module ConnectionAdapters
    module PostgreSQL
      module OID # :nodoc:
        class DateTime < Type::DateTime # :nodoc:
          include Infinity

          def type_cast_for_database(value)
            if has_precision? && value.acts_like?(:time) && value.year <= 0
              bce_year = format("%04d", -value.year + 1)
              super.sub(/^-?\d+/, bce_year) + " BC"
            else
              super
            end
          end

          def cast_value(value)
            if value.is_a?(::String)
              case value
              when 'infinity' then ::Float::INFINITY
              when '-infinity' then -::Float::INFINITY
              when / BC$/
                astronomical_year = format("%04d", -value[/^\d+/].to_i + 1)
                super(value.sub(/ BC$/, "").sub(/^\d+/, astronomical_year))
              else
                super
              end
            else
              value
            end
          end
        end
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

同样,您将无法使用浮点数进行日期时间比较。但是,它可能不够有这两个值的特殊情况简单-::Float::INFINITY::Float::INFINITY