PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Probleme mit unendlichem Zeitbereich in Rails

Sie können Infinity nicht als Teil eines Zeitbereichs in Rails speichern. Ich glaube, das liegt daran, dass Infinity als String-Wert eingefügt und als Float interpretiert wird, wenn es aus dem nativen PSQL-Oid gezogen wird. Daher ist kein Datumsbereich von Date -> Float möglich. Aber Sie können es schaffen, Ihren eigenen Bereich mit Pseudodaten (in 1 Million Jahren) zu erstellen, oder Sie können einfach zwei separate Datumsfelder verwenden und sie im Modell entsprechend interpretieren. Startdatum, Enddatum.

In Rails 4.2+ können Sie einen Float::INFINITY-Wert in Ihrem datetime-Typ speichern. Beispiel.

User.first.update(begin_date: DateTime.now, end_date: 'infinity')
User.first.end_date # => Infinity

Jedoch end_date ist kein gültiges Datum. Sie speichern nur den String in der Datenbank und Sie ziehen einen Float heraus wenn du es anrufst.

Hier ist der eigentliche Code (Rails 4.2), der das handhabt:

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

Auch hier werden Sie nicht in der Lage sein, Datumszeitvergleiche mit einem Float durchzuführen. Aber es ist wahrscheinlich einfach genug, einen Sonderfall für diese beiden Werte -::Float::INFINITY zu haben und ::Float::INFINITY