Ich importiere Daten aus einer CSV-Datei und möchte meinem Benutzer erlauben, das Format für eine DateTime-Spalte anzugeben. Anstatt ihnen zu erlauben, eine Formatzeichenkette einzutippen und mit dem Schmerz der Validierung der Eingabe fertig zu werden, wollte ich ihnen eine Auswahlbox geben, die alle Formatoptionen auflistet (z. B. %m/%d/%Y
, etc ...). Jemand erwähnte, dass bereits ein Edelstein existiert, der alle vernünftigen DateTime-Formate auflistet, aber ich konnte ihn nicht finden. Wie bekomme ich eine Liste der verfügbaren DateTime-Formate zur Anzeige?Ruby: List DateTime Format Optionen
Antwort
Sie könnten an einer anderen Alternative interessiert sein. Ich musste vor nicht allzu langer Zeit etwas Ähnliches machen und fast beliebige Datumsformate unterstützen. Am Ende haben wir 29 verschiedene Formate (alle in den USA und Kanada) aus allen von uns unterstützten Datenquellen (CSV-Dateien) gefunden.
kam ich mit dieser Klasse bis zu dem Ergebnis zu analysieren und Cache:
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
Das die Chronic gem verwendet einige des Datums-Parsers zu tun, basierend auf einer anfängliche Regex den Parsing-Weg zu wählen, als auch als einige notwendige Korrekturen, denen wir auf dem Weg begegneten. Korrektheit und Geschwindigkeit waren die Hauptziele dieses Ansatzes. Durch das Zwischenspeichern der Ergebnisse wurde die Verarbeitung von Daten aus der CSV-Datei in den meisten Fällen um das 5-fache oder mehr beschleunigt.
Wenn Sie nicht möchten, dass der Benutzer gefragt wird, welches Format er verwendet hat, und einfach mit dem Konsumieren von Daten fortfahren, die Sie wählen, sollte Ihnen dies das geben, was Sie brauchen.
Überprüfen Sie die DateTime
Klasse. Es ist Teil der Standardbibliothek, kein externer Edelstein. Sie müssen require date
verwenden, um es zu verwenden.
Hier sind einige Beispiele in irb; Beachten Sie, dass Sie mit strftime
viel Flexibilität haben und Ihre eigene Formatzeichenfolge angeben müssen.
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"
Willkommen bei SO. "Fragen, die uns auffordern, ein Buch, ein Tool, eine Softwarebibliothek, ein Tutorial oder eine andere Offsite-Ressource zu empfehlen oder zu finden, sind für Stack Overflow off-topic, da sie eher zu eigensinnigen Antworten und Spam neigen. //meta.stockoverflow.com/questions/254393) und was bisher getan wurde, um es zu lösen. " –