how to convert a hash value returned from a date_select in rails to a Date object?

前端 未结 5 1648
感动是毒
感动是毒 2020-12-18 00:50

I have a date_select in my view inside a form, however on submit the value returned is in a hash form like so:

{\"(1i)\"=>\"2010\", \"(2i)\"=>\"8\", \"         


        
相关标签:
5条回答
  • 2020-12-18 01:13
    Date.new(*params["due_date"].values.map(&:to_i))
    

    Note: Works in ruby 1.9.2+ since it depends on the order of the hash elements.

    Two goodies here:

    • Symbol to Proc
    • Splat operator
    0 讨论(0)
  • 2020-12-18 01:29

    This particular code (the one that does conversion) can be tracked from lib/active_record/connection_adapters/abstract/schema_definitions.rb, line no 67 onwards, i.e. the method type_cast.

    These two methods are used to generate a date from string:

    def fast_string_to_date(string)
      if string =~ Format::ISO_DATE
        new_date $1.to_i, $2.to_i, $3.to_i
      end
    end
    
    # Doesn't handle time zones.
    def fast_string_to_time(string)
      if string =~ Format::ISO_DATETIME
        microsec = ($7.to_f * 1_000_000).to_i
        new_time $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, microsec
      end
    end
    
    # Note that ISO_DATE is:
    ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
    
    0 讨论(0)
  • 2020-12-18 01:35

    Here's a generic way to do it, which also supports partial dates/times and empty fields:

    def date_from_date_select_fields(params, name)
      parts = (1..6).map do |e|
        params["#{name}(#{e}i)"].to_i
      end
    
      # remove trailing zeros
      parts = parts.slice(0, parts.rindex{|e| e != 0}.to_i + 1)
      return nil if parts[0] == 0  # empty date fields set
    
      Date.new(*parts)
    end
    

    Example usage:

    # example input:
    #
    # params = {
    #   "user":
    #     "date_of_birth(1i)": "2010",
    #     "date_of_birth(2i)": "8",
    #     "date_of_birth(3i)": "16"
    #   }
    # }
    date_of_birth = date_from_date_select_fields(params[:user], 'date_of_birth')
    
    0 讨论(0)
  • 2020-12-18 01:37

    I have a short one line solution for this

    params["due_date"] = {"date(3i)"=>"14", "date(2i)"=>"4", "date(1i)"=>"2014"}
    
    
    params["due_date"].map{|k,v| v}.join("-").to_date
    => Mon, 14 Apr 2014
    
    0 讨论(0)
  • 2020-12-18 01:38

    I don't know about a rails way, but this "one-liner" does the trick:

    irb(main):036:0> d = Date.parse( {"(1i)"=>"2010", "(2i)"=>"8", "(3i)"=>"16"}.to_a.sort.collect{|c| c[1]}.join("-") )
    => #<Date: 4910849/2,0,2299161>
    irb(main):037:0> d.to_s
    => "2010-08-16"
    

    Or, with less magic:

    h={"(1i)"=>"2010", "(2i)"=>"8", "(3i)"=>"16"}
    d=Date.new(h['(1i)'].to_i, h['(2i)'].to_i, h['(3i)'].to_i)
    d.to_s
    => "2010-08-16"
    
    0 讨论(0)
提交回复
热议问题