你如何使用Ruby CSV转换器?

dfr*_*kow 14 ruby csv

假设您有以下文件:

textfield,datetimefield,numfield
foo,2008-07-01 17:50:55.004688,1
bar,2008-07-02 17:50:55.004688,2
Run Code Online (Sandbox Code Playgroud)

读取.csv的Ruby代码如下:

#!/usr/bin/env ruby

require 'csv'

csv = CSV($stdin, :headers => true, :converters => :all)
csv.each do |row|
  print "#{row}"
  the_date = row['datetimefield'].to_date
end
Run Code Online (Sandbox Code Playgroud)

该代码提供此错误消息:

./foo2.rb:8:in `block in <main>': undefined method `to_date' for "2008-07-01 17:50:55.004688":String (NoMethodError)
Run Code Online (Sandbox Code Playgroud)

是什么赋予了?

我已经阅读了文档,但我没理解.

编辑:是的,我可以单独解析字段.这个问题的关键是我想学习如何使用记录的转换器功能.

knu*_*nut 27

您在询问如何使用转换器.

我的例子定义了新转换器的用法mytime.转换器my_time尝试在可能的情况下构建时间对象.

#Define test data
src = <<csv
textfield,datetimefield,numfield
foo,2008-07-01 17:50:55.004688,1
bar,2008-07-02 17:50:55.004688,2
csv

require 'csv'
require 'time'
CSV::Converters[:mytime] = lambda{|s| 
  begin 
    Time.parse(s)
  rescue ArgumentError
    s
  end
}

csv = CSV(src, :headers => true, :converters => [:mytime])
csv.each do |row|
  print "#{row}"
  the_date = row['datetimefield'].to_date
end
Run Code Online (Sandbox Code Playgroud)

使用此技术,您还可以定义转换器以从类似时间的字符串创建日期.该解决方案还保留所有其他转换器.

#define test data
src = <<csv
textfield,datetimefield,numfield
foo,2008-07-01 17:50:55.004688,1
bar,2008-07-02 17:50:55.004688,2
csv

require 'csv'
require 'time'
CSV::Converters[:time2date] = lambda{|s| 
  begin 
    Time.parse(s).to_date
  rescue ArgumentError
    s
  end
}

csv = CSV(src, :headers => true, :converters => CSV::Converters.keys + [:time2date])
csv.each do |row|
  print "#{row}"
  p row['datetimefield'] #Date-field
end
Run Code Online (Sandbox Code Playgroud)


Fre*_*ung 7

您的日期时间与CSV::DateTimeMatcherCSV用于决定是否应尝试日期时间转换的正则表达式不匹配.根据它的外观,它是这样做的,因为你已经得到了几分之一秒.

您可以覆盖该常量或编写自己的转换器(DateTime.parse似乎对您的字符串感到满意)