你如何使用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