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 ’

~> from -:16:in `block in ’

On Feb 16, 2014, at 9:12 AM, Arup R. [email protected] wrote:

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

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

Ammar A. 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]