2016-05-20 12 views
0

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

+0

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. " –

Antwort

1

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.

1

Ü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"