2016-12-21 68 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

请试试这个

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