Question

I am importing a CSV file that contains fields that need to be converted as follows:

  • "True" (string) -> true (boolean)
  • "False" (string) -> false (boolean)
  • "%m/%d/%Y" (string format) -> Date object
  • "%m/%d/%Y %I:%M:%S %p" (string format) -> DateTime object

The default CSV converters don't match the Date and DateTime fields. This method below seems to work, but wonder if there is a better way, possibly by override the matching pattern used by the converters?

 require 'csv'
 require 'date'

 src = <<csv
 active,date_created,date_modified
 "True","03/12/2012","03/12/2012 2:14:23 PM"
 "False","01/25/2011","03/12/2013 3:14:27 AM"
 csv

 CSV::Converters[:my_converters] = lambda{|field| 
   begin 
     case field.to_s
       when "True"
         true
       when "False"
         false
       when /^\d{2}\/\d{2}\/\d{4}$/
         Date.strptime(field,"%m/%d/%Y")
       else
         DateTime.strptime(field,"%m/%d/%Y %I:%M:%S %p")
       end
   rescue ArgumentError
     field
   end
 }

 csv = CSV(src, :headers => true, :converters => [:my_converters])
 csv.each{|row| puts row}

true,2012-03-12,2012-03-12T14:14:23+00:00

false,2011-01-25,2013-03-12T03:14:27+00:00

Was it helpful?

Solution 2

This is the proper way to do things if the default converters aren't sufficient. My only suggestion would be to separate your converters into different lambdas since the CSV library is already designed to test each field against an array of converters (making your case redundant).

But if this is just a quick one-off script, what you have is good enough.

OTHER TIPS

Convert fields accordingly field's name (header's name)

custom_converter = lambda { |value, field_info|
  case field_info.header
  when 'OrderUuid', 'Exchange', 'Type', 'OrderType'
    value.to_s
  when 'Quantity', 'Limit', 'CommissionPaid', 'Price'
    value.to_f
  when 'Opened', 'Closed'
    Time.zone.parse(value)
  else
    fail("Unknown field name #{field_info.inspect}=#{value}")
  end
}

CSV.parse(content, headers: :first_row, converters: [custom_converter]).map(&:to_h)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top