2016-12-21 16 views
0

私はlog/archive/2016-12-21.zipのような文字列を持っており、日付部分を抽出する必要があります。ファイルパス文字列から日付部分を抽出します

は、これまでのところ私はこれらのソリューションを試してみました:

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 

は、これを行うのより良い方法はありますか?

+1

ドットは、常に最後に来なければならないならば、あなたはこの '「ログ/アーカイブ/ 2016-12-21.zip」をしようとします。 split(/[\/.]/)[- 2] ' –

+0

はいドットはいつも最後に来る – Thorin

+0

それは最も簡単な解決策ではない、私はいつも正規表現(\ /(\ d {4} - \ d {2} - \ d {2})\ .zip)。理由は、マッチでテストすることができ、文字列の構造が変更されたかどうかを確実に検出するからです。私は数字2がどのように動作するのかわかりませんが、数字のない文字列を評価することができるので、数字3は使わないでしょう... –

答えて

4

あなたは拡張子を渡しFile.basenameを使用することができます。

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

あなたは値がDateになりたい場合は、単に `日付に文字列を変換するためにDate.parseを使用しています。

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

文字列がディレクトリから読み取られた場合、これは本当に良いでしょう溶液。しかし、興味のない私の質問、ファイル名に有効な日付がない場合はどうなりますか?そのような場合には、 "log/archive/12-21.zip" –

+0

@DoktorOSwaldoのように、値を直接 'Date.parse'に渡すのではなく、自分で解析して日付を作成する必要があります。 –

+0

ええ、この場合はルビーの動作を知っていますか?失敗して例外が出ますか?それとも1970-12-21のようなものになるのだろうか? –

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" 
    #=> [] 

あなただけではなく、日付オブジェクトより日付文字列を、したい場合は、次のように方法を変更します。

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

日付形式が無効である場合、それはnilを返します。この

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

を試してみてください。

例: -

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

はそれがお役に立てば幸いです。

1

この正規表現は、ほとんどの場合をカバーする必要があります。これは、年、月、日の間に任意の非桁を可能にする:

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] 
関連する問題