Trouble with CSV custom Converter

I am getting an error from my code. Could anyone point me what wrong I
made here -

require 'csv'
require 'date'

src = <<csv
Date, Time, Open, Close, High, Low, Volume
2007.01.02,07:00,119.01,119.01,119.01,119.01,8
2008.01.02,07:01,119.01,119.01,119.01,119.01,8
2007.01.02,08:02,119.01,119.01,119.01,119.01,8
2010.01.02,07:03,119.01,119.02,119.01,119.02,8
2011.01.02,07:04,119.02,119.03,119.01,119.02,8
csv

File.write('test.csv',src)

CSV::Converters[:weekday] = lambda do |s|
  begin
  Date.parse(s)
  rescue ArgumentError
    Date.strptime(s, '%Y.%m.%d').wday
  end
end

CSV::Converters[:time_am_pm] = lambda do |s|
  begin
  Date.parse(s)
  rescue ArgumentError
    Date.strptime(s, '%H:%M').strftime("%A")
  end
end

CSV.foreach('test.csv', :converters => [:weekday,
:numeric,:time_am_pm],:headers => true) do |row|
  p row
end

# ~> -:19:in `strptime': invalid date (ArgumentError)
# ~> from -:19:in `rescue in block in <main>'
# ~> from -:16:in `block in <main>'

···

--
Posted via http://www.ruby-forum.com/.

If you add a puts in that block you will see that the conversion is failing when it is attempted on the second column, the time. I believe that you should return the input value (s here) if the conversion fails, so that other conversions get attempted. Also, note that the weekday conversion is never applied because wday is only called in the rescue block.

This should make the conversion if it is possible and pass if it isn't:

CSV::Converters[:weekday] = lambda {|s|
  begin
    Date.parse(s).wday # call wday here
  rescue
    s # return the input as is
  end
}

The same applies to the other conversion.

Regards,
Ammar

···

On Feb 16, 2014, at 9:12 AM, Arup Rakshit <lists@ruby-forum.com> wrote:

CSV::Converters[:weekday] = lambda do |s|
begin
Date.parse(s)
rescue ArgumentError
   Date.strptime(s, '%Y.%m.%d').wday
end
end

Ammar Ali wrote in post #1136826:

If you add a puts in that block you will see that the conversion is
failing when it is attempted on the second column, the time. I believe
that you should return the input value (s here) if the conversion fails,
so that other conversions get attempted. Also, note that the weekday
conversion is never applied because wday is only called in the rescue
block.

Good tips!! I am done.

require 'csv'
require 'date'
require 'time'

src = <<csv
Date, Time, Open, Close, High, Low, Volume
2007.01.02,07:00,119.01,119.01,119.01,119.01,8
2008.01.02,07:01,119.01,119.01,119.01,119.01,8
2007.01.02,08:02,119.01,119.01,119.01,119.01,8
2010.01.02,07:03,119.01,119.02,119.01,119.02,8
2011.01.02,07:04,119.02,119.03,119.01,119.02,8
csv

File.write('test.csv',src)

CSV::Converters[:weekday] = lambda do |s|
  begin
    Date.strptime(s, '%Y.%m.%d').strftime("%A")
  rescue ArgumentError
    s
  end
end

CSV::Converters[:time_am_pm] = lambda do |s|
  begin
    Time.strptime(s, '%H:%M').strftime("at %I:%M%p")
  rescue ArgumentError
    s
  end
end

CSV.foreach('test.csv', :converters => [:weekday,
:numeric,:time_am_pm],:headers => true) do |row|
  p row.fields
end

# >> ["Tuesday", "at 07:00AM", 119.01, 119.01, 119.01, 119.01, 8]
# >> ["Wednesday", "at 07:01AM", 119.01, 119.01, 119.01, 119.01, 8]
# >> ["Tuesday", "at 08:02AM", 119.01, 119.01, 119.01, 119.01, 8]
# >> ["Saturday", "at 07:03AM", 119.01, 119.02, 119.01, 119.02, 8]
# >> ["Sunday", "at 07:04AM", 119.02, 119.03, 119.01, 119.02, 8]

···

--
Posted via http://www.ruby-forum.com/\.