PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Problemi con intervallo di tempo infinito in Rails

Non puoi memorizzare Infinity come parte di un intervallo di tempo in Rails. Credo che ciò sia dovuto al fatto che Infinity verrà inserito come valore stringa e interpretato come float quando viene estratto dall'oid PSQL nativo. Pertanto, qualsiasi intervallo di date da Data -> Mobile non sarà valido. Ma puoi riuscire a creare il tuo intervallo con date pseudo (1 milione di anni da oggi) oppure puoi semplicemente utilizzare due campi di data separati e interpretarli in modo appropriato nel modello. Data di inizio, data di fine.

In Rails 4.2+, puoi memorizzare un valore Float::INFINITY all'interno del tuo tipo datetime. Esempio.

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

Tuttavia, end_date non sarà una data valida. Stai solo memorizzando la stringa nel database e stai estraendo un flottante quando lo chiami.

Ecco il codice effettivo (Rails 4.2) che lo gestisce:

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

Ancora una volta, non essere in grado di fare confronti di data e ora con un float. Ma probabilmente è abbastanza semplice avere un caso speciale per questi due valori -::Float::INFINITY e ::Float::INFINITY