J'importe des données à partir d'un fichier CSV et je souhaite autoriser mon utilisateur à spécifier le format d'une colonne DateTime. Plutôt que de leur permettre de taper une chaîne de format et de gérer la peine de valider l'entrée, je prévoyais de leur donner une boîte de sélection qui répertorie toutes les options de format (par exemple %m/%d/%Y
, etc ...). Quelqu'un a mentionné qu'une gemme existe déjà qui énumérera tous les formats DateTime raisonnables, mais j'ai été incapable de le trouver. Comment puis-je obtenir une liste des formats DateTime disponibles pour l'affichage?Ruby: Liste des options de format DateTime
Répondre
Vous pourriez être intéressé par une autre alternative. J'ai dû faire quelque chose de similaire il n'y a pas si longtemps, et supporter des formats de dates presque arbitraires. En fin de compte, nous avons détecté 29 formats distincts (tous les États-Unis et le Canada) de toutes les sources de données (fichiers CSV) que nous avons pris en charge.
je suis venu avec cette classe pour analyser et mettre en cache le résultat:
class DateParser
@@date_cache = {}
def self.is_date?(date)
return self.match_digital_date?(date) || self.match_instance_date?(date)
end
def self.parse_date(date)
return nil if date.blank?
return date if date.instance_of?(Date)
date = date.to_s
cached_date = @@date_cache[date]
return cached_date if !cached_date.nil?
match = self.match_instance_date?(date)
if !match.nil?
month_str = match[1].upcase
day = match[2].to_i
year = match[3].to_i
year += (year < 20) ? 2000 : 1900 if year < 1600
month = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'].find_index {|mon| mon == month_str }
cached_date = Date.new(year, month+1, day) if !month.nil?
else
scrubbed_date = date.gsub(/^([0-9]+)[\/-]+([0-9]+)[\/-]+00$/, '\\1/\\2/2000')
begin
parsed = Chronic.parse(scrubbed_date)
rescue
parsed = nil
end
return nil if parsed.nil?
cached_date = parsed.to_date
end
@@date_cache[date] = cached_date
return cached_date
end
private
# Matches dates in these formats
# : 2015-01-13
# : 01-13-2015
# : 01-13-15
# : 13-01-15
# : 01/13/2015
# : 01/13/15
# : 13/01/15
def self.match_digital_date?(date)
return /^([0-9]+)[\/-]+([0-9]+)[\/-]+([0-9]+)$/.match(date)
end
def self.match_instance_date?(date)
return /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d+)\/(\d+)/i.match(date)
end
end
Il utilise le Chronic gem pour faire partie de l'analyse de ce jour, à partir d'une correspondance initiale de regex pour choisir le chemin d'analyse syntaxique, ainsi comme certains correctifs nécessaires que nous avons rencontrés en cours de route. L'exactitude et la rapidité étaient les principaux objectifs de cette approche. La mise en cache des résultats a permis d'accélérer le traitement des dates du fichier CSV de 5X ou plus dans la plupart des cas.
Si vous ne voulez pas demander à l'utilisateur quel format il a utilisé et si vous voulez simplement consommer les dates que vous choisissez, cela devrait vous donner ce dont vous avez besoin.
Consultez la classe DateTime
. Il fait partie de la bibliothèque standard, pas une gemme externe. Vous aurez besoin de require date
pour l'utiliser.
Voici quelques exemples dans irb; notez qu'avec strftime
vous avez beaucoup de flexibilité et devrez spécifier votre propre chaîne de format.
2.3.0 :007 > dt = DateTime.now
=> #<DateTime: 2016-05-21T03:16:51+08:00 ((2457529j,69411s,139202000n),+28800s,2299161j)>
2.3.0 :008 > dt.iso8601
=> "2016-05-21T03:16:51+08:00"
2.3.0 :009 > dt.xmlschema
=> "2016-05-21T03:16:51+08:00"
2.3.0 :010 > dt.jisx0301
=> "H28.05.21T03:16:51+08:00"
2.3.0 :011 > dt.rfc3339
=> "2016-05-21T03:16:51+08:00"
2.3.0 :012 > dt.httpdate
=> "Fri, 20 May 2016 19:16:51 GMT"
2.3.0 :013 > dt.strftime('%Y-%m-%dT%H:%M:%S%z')
=> "2016-05-21T03:16:51+0800"
Bienvenue chez SO. «Les questions qui nous demandent de recommander ou de trouver un livre, un outil, une bibliothèque de logiciels, un didacticiel ou autre ressource hors site sont hors sujet pour Stack Overflow, car elles ont tendance à attirer les réponses avisées et le spam. //meta.stackoverflow.com/questions/254393) et ce qui a été fait jusqu'à présent pour le résoudre. " –