sql >> Databasteknik >  >> RDS >> PostgreSQL

Problem med oändligt tidsintervall i Rails

Du kan inte lagra Infinity som en del av ett tidsintervall i Rails. Jag tror att detta beror på att Infinity kommer att infogas som ett strängvärde och tolkas som en float när den dras ut från den ursprungliga PSQL-oiden. Så alla datumintervall från Date -> Float kommer inte att vara genomförbara. Men du kan skapa ditt eget intervall med pseudodatum (1 miljon år från nu) eller så kan du bara använda två separata datumfält och tolka dem på rätt sätt i modellen. Startdatum, slutdatum.

I Rails 4.2+ kan du lagra ett Float::INFINITY-värde i din datetime-typ. Exempel.

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

Men end_date kommer inte att vara ett giltigt datum. Du lagrar bara strängen i databasen och du drar ut en float när du ringer det.

Här är den faktiska (Rails 4.2) koden som hanterar det:

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

Återigen, du kommer inte kunna göra datum-tidsjämförelser med en float. Men det är förmodligen tillräckligt enkelt att ha ett specialfall för dessa två värden -::Float::INFINITY och ::Float::INFINITY




  1. PHP echo SQL Count

  2. PLS-00306:fel nummer eller typer av argument i anrop till 'OUTPUT_ARRAY'

  3. Använder ORDER BY och GROUP BY tillsammans

  4. Hur kan jag välja endast den första distinkta matchningen från ett fält i MySQL?