你如何使用Ruby CSV转换器?

假设您有以下文件:

textfield,datetimefield,numfield foo,2008-07-01 17:50:55.004688,1 bar,2008-07-02 17:50:55.004688,2 

读取.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 

该代码提供此错误消息:

 ./foo2.rb:8:in `block in ': undefined method `to_date' for "2008-07-01 17:50:55.004688":String (NoMethodError) 

是什么赋予了?

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

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

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

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

您在问如何使用转换器。

我的例子定义了一个新的转换器mytime的用法。 如果可能,转换器my_time会尝试构建时间对象。

 #Define test data src = < true, :converters => [:mytime]) csv.each do |row| print "#{row}" the_date = row['datetimefield'].to_date end 

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

 #define test data src = < true, :converters => CSV::Converters.keys + [:time2date]) csv.each do |row| print "#{row}" p row['datetimefield'] #Date-field end 

作品!!! 可执行版代码:

 #Define test data src = "textfield,datetimefield,numfield\n" + "foo,2008-07-01 17:50:55.004688,1\n" + "bar,2008-07-02 17:50:55.004688,2" require 'csv' require 'time' CSV::Converters[:mytime] = lambda{|s| begin Time.parse(s) rescue ArgumentError s end } csv = CSV(src, :headers => true, :converters => [:mytime]) array_of_hash_objects = csv.to_a.map {|row| row.to_hash } array_of_hash_objects.each do |row| print "#{row}" the_date = row['datetimefield'].to_date puts print the_date puts end 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]) array_of_hash_objects = csv.to_a.map {|row| row.to_hash } array_of_hash_objects.each do |row| print "#{row}" puts p row['datetimefield'] #Date-field end 

=============

输出:

 {"textfield"=>"foo", "datetimefield"=>2008-07-01 17:50:55 -0400, "numfield"=>"1"} 2008-07-01 {"textfield"=>"bar", "datetimefield"=>2008-07-02 17:50:55 -0400, "numfield"=>"2"} 2008-07-02 {"textfield"=>"foo", "datetimefield"=>2008-07-01 17:50:55 -0400, "numfield"=>1} 2008-07-01 17:50:55 -0400 {"textfield"=>"bar", "datetimefield"=>2008-07-02 17:50:55 -0400, "numfield"=>2} 2008-07-02 17:50:55 -0400