2016-12-21 1 views
0

Ich habe eine Zeichenfolge, die wie folgt aussieht: log/archive/2016-12-21.zip, und ich muss den Datumsteil extrahieren.Extract date Teil aus einer Datei Pfadzeichenfolge

Bisher habe ich diese Lösungen ausprobiert:

1) ["log/archive/2016-12-21.zip"].map{|i|i[/\d{4}-\d{2}-\d{2}/]}.first 
2) "log/archive/2016-12-21.zip".to_date 
3) "log/archive/2016-12-21.zip".split("/").last.split(".").first 

Gibt es einen besseren Weg, dies zu tun?

+1

wenn der Punkt sollte immer erst in letzter kommt dann können Sie versuchen, diese '„log/Archiv/2016-12-21.zip“. split (/[\/.]/)[- 2] ' –

+0

Ja Punkt wird immer immer kommen – Thorin

+0

Auch ist es nicht die einfachste Lösung, ich würde immer mit einer Regex (\/(\ d {4} - \ d {2} - \ d {2}) \. zip). Der Grund ist, dass Sie es mit einer Übereinstimmung testen können, und Sie werden sicherlich feststellen, ob sich die Struktur der Zeichenfolge ändert. Ich weiß nicht, wie Nummer 2 sich verhält, aber ich würde nicht mit Nummer 3 gehen, da es Strings ohne Datumsangaben überhaupt auswerten kann ... –

Antwort

4

Sie können File.basename verwenden, um die Erweiterung vorbei:

File.basename("log/archive/2016-12-21.zip", ".zip") 
# => "2016-12-21" 

Wenn Sie den Wert wollen Date.parse ein Date zu sein, verwenden Sie einfach die Zeichenfolge in eine `Datum zu konvertieren.

require 'date' 
Date.parse(File.basename("log/archive/2016-12-21.zip", ".zip")) 
+0

Wenn die Strings aus einem Verzeichnis gelesen werden, wäre das ein wirklich gutes Lösung. Aber meine Frage aus Interesse, was passiert, wenn es im Dateinamen kein gültiges Datum gibt? zum Beispiel "log/archive/12-21.zip" –

+0

@DoktorOSwaldo in diesem Fall, anstatt den Wert direkt an 'Date.parse' zu ​​übergeben, müssen Sie selbst mit dem Parsen umgehen und ein Datum zusammenstellen. –

+0

Ja, aber weißt du das Verhalten von Ruby in diesem Fall, wird es scheitern und eine Ausnahme geben? oder wird es etwas wie 1970-12-21 sein? –

0
require 'date' 

def pull_dates(str) 
    str.split(/[\/.]/).map { |s| Date.strptime(s, '%Y-%m-%d') rescue nil }.compact 
end 

pull_dates "log/archive/2016-12-21.zip" 
    #=> [#<Date: 2016-12-21 ((2457744j,0s,0n),+0s,2299161j)>] 
pull_dates "log/2016-12-21/archive.zip" 
    #=> [#<Date: 2016-12-21 ((2457744j,0s,0n),+0s,2299161j)>] 
pull_dates "log/2016-12-21/2016-12-22.zip" 
    #=> [#<Date: 2016-12-21 ((2457744j,0s,0n),+0s,2299161j)>, 
    # #<Date: 2016-12-22 ((2457745j,0s,0n),+0s,2299161j)>] 
pull_dates "log/2016-12-21/2016-12-32.zip" 
    #=> [#<Date: 2016-12-21 ((2457744j,0s,0n),+0s,2299161j)>] 
pull_dates "log/archive/2016A-12-21.zip" 
    #=> [] 
pull_dates "log/archive/2016/12/21.zip" 
    #=> [] 

Wenn Sie das Datum Zeichenfolge nur wollen, anstatt das Datum Objekt, das Verfahren wie folgt ändern.

def pull_dates(str) 
    str.split(/[\/.]/). 
     each_with_object([]) { |s,a| 
     a << s if (Date.strptime(s, '%Y-%m-%d') rescue nil)} 
end 

pull_dates "log/archive/2016-12-21.zip" 
    #=> ["2016-12-21"] 
0

Bitte versuchen Sie diese

"log/archive/2016-12-21.zip".scan(/\d{4}-\d{2}-\d{2}/).pop 
=> "2016-12-21" 

Wenn das Datumsformat ist ungültig, es null zurück.

Beispiel: -

"log/archive/20-12-21.zip".scan(/\d{4}-\d{2}-\d{2}/).pop 
      ^^ 
=> nil 

Hoffe, es hilft.

1

Dieser Regex sollte die meisten Fälle abdecken. Es ermöglicht eine optionale nicht-Zahl zwischen Jahr, Monat und Tag:

require 'date' 

def extract_date(filename) 
    if filename =~ /((?:19|20)\d{2})\D?(\d{2})\D?(\d{2})/ then 
    year, month, day = $1.to_i, $2.to_i, $3.to_i 
    # Do something with year, month, day, or just leave it like this to return an array : [2016, 12, 21] 
    # Date.new(year, month, day) 
    end 
end 

p extract_date("log/archive/2016-12-21.zip") 
p extract_date("log/archive/2016.12.21.zip") 
p extract_date("log/archive/2016:12:21.zip") 
p extract_date("log/archive/2016_12_21.zip") 
p extract_date("log/archive/20161221.zip") 
p extract_date("log/archive/2016/12/21.zip") 
p extract_date("log/archive/2016/12/21") 
#=> Every example returns [2016, 12, 21] 
Verwandte Themen