2013-10-09 3 views
1

Je suis d'importer un fichier CSV qui contient des champs qui doivent être convertis comme suit:convertisseurs personnalisés Ruby CSV pour plusieurs champs

  • "True" (string) -> true (Boolean)
  • « Faux "(string) -> false (Boolean)
  • "% m /% d /% Y"(format string) -> objet date
  • " % m /% d /% Y% H:% m:% S% p "(format de chaîne) -> objet DateTime

Les convertisseurs CSV par défaut ne correspondent pas aux champs Date et DateTime. Cette méthode ci-dessous semble fonctionner, mais se demander s'il existe une meilleure façon, éventuellement en remplaçant le modèle de correspondance utilisé par les convertisseurs?

require 'csv' 
require 'date' 

src = <<csv 
active,date_created,date_modified 
"True","03/12/2012","03/12/2012 2:14:23 PM" 
"False","01/25/2011","03/12/2013 3:14:27 AM" 
csv 

CSV::Converters[:my_converters] = lambda{|field| 
    begin 
    case field.to_s 
     when "True" 
     true 
     when "False" 
     false 
     when /^\d{2}\/\d{2}\/\d{4}$/ 
     Date.strptime(field,"%m/%d/%Y") 
     else 
     DateTime.strptime(field,"%m/%d/%Y %I:%M:%S %p") 
     end 
    rescue ArgumentError 
    field 
    end 
} 

csv = CSV(src, :headers => true, :converters => [:my_converters]) 
csv.each{|row| puts row} 

vrai, 2012-03-12,2012-03-12T14: 14: 23 + 00: 00

faux, 2011-01-25,2013-03-12T03: 14: 27+ 00:00

Répondre

1

C'est la bonne façon de faire les choses si les convertisseurs par défaut ne sont pas suffisants. Ma seule suggestion serait de séparer vos convertisseurs en différents lambdas puisque la bibliothèque CSV est déjà conçue pour tester chaque champ par rapport à une série de convertisseurs (rendant votre case redondant). Mais si c'est juste un script rapide, ce que vous avez est assez bon.

Questions connexes