2015-04-21 102 views
1

我有日期的数组,我需要每个日期弄清楚下一个日期间的差异,从而例如遍历日期来查找日期

a= {1=>03-01-2015, 2=>03-10-2015, 3=>03-15-2015, 4=>03-27-2015} 

完整的对象看起来是这样的间隔天.. 。

#<Transaction:0xc413c58 @id="KYYEZEPedacrwBkpqDk8C5Yy04BqvJIXJdYXJ", @account="Ppp575Ke19T8PxrAdMrNUq4Ox4AQVrHMLa5D0", @date="2013-10-23", @amount=100, @name="COMED", @meta={"is_risky"=>false, "location"=>{"store_number"=>"10782"}}, @location=nil, @pending=false, @score={"location"=>{}, "name"=>0.2}, @type={"primary"=>"unresolved"}, @category=nil, @category_id=nil>] 

应该返回

{9,5,12} #the days between each 2 dates 

这里是我迄今为止...

@collect_transactions = (@user.transactions.find_all { |t| t.name == 'due_at' }) 
@date_difference = @collect_transactions.map(&:date).each_cons(2) { |a,b| b-a } 

我不知道,如果是each_cons正确的方法,但我的反应,现在是这样的......

NoMethodError: undefined method `-' for "2015-01-15":String 

它不是数着日子...任何建议,将不胜感激

+0

这个问题有些含糊之处。首先,你说你有一个日期数组,但显示一个“哈希”。此外,问题中还混合了两种不同的日期格式。请整理出来帮助我们给出更准确的答案。 – Drenmi

回答

3

是的,Enumerable#each_cons是要走的路。您只需首先将日期字符串转换为日期对象。你可以这样做,如下所示。

代码

require 'date' 

def date_diffs(h)  
    h.values. 
    map { |s| Date.strptime(s,'%m-%d-%Y') }. 
    each_cons(2). 
    map { |d1,d2| (d2-d1).to_i } 
end 

h = { 1=>"03-01-2015", 2=>"03-10-2015", 3=>"03-15-2015", 4=>"03-27-2015" } 

date_diffs(h) 
    #=> [9, 5, 12] 

讨论

从编辑你的问题,看来你可能需要使用的日期格式字符串'%Y-%m-%d' 。另一种选择是使用Date::parse而不是Date::strptime。 (我通常更喜欢strptime,因为它要求更高。)

您当然必须确保散列值的顺序是正确的。如果您使用的是1.9之前版本的Ruby(当不能保证散列键的顺序,或者甚至是键顺序的概念时),或者您使用更新版本(其中维护键放置顺序时),但不确定的键的顺序,你可以这样做,作为第一步:

values = h.values_at(*(1..4)) 
    #=> ["03-01-2015", "03-10-2015", "03-15-2015", "03-27-2015"] 

说明

我们:

b = h.values 
    #=> ["03-01-2015", "03-10-2015", "03-15-2015", "03-27-2015"] 
c = b.map { |s| Date.strptime(s,'%m-%d-%Y') } 
    #=> [#<Date: 2015-03-01 ((2457083j,0s,0n),+0s,2299161j)>, 
    # #<Date: 2015-03-10 ((2457092j,0s,0n),+0s,2299161j)>, 
    # #<Date: 2015-03-15 ((2457097j,0s,0n),+0s,2299161j)>, 
    # #<Date: 2015-03-27 ((2457109j,0s,0n),+0s,2299161j)>] 
d = c.each_cons(2) 
    #=> #<Enumerator: [#<Date: 2015-03-01.... 

我们看到,枚举d含有d.size #=> 3元素。将传递到块和分配给该块的变量的第一个元素是:

d1,d2 = d.next 
    #=> [#<Date: 2015-03-01 ((2457083j,0s,0n),+0s,2299161j)>, 
    # #<Date: 2015-03-10 ((2457092j,0s,0n),+0s,2299161j)>] 
d1 #=> #<Date: 2015-03-01 ((2457083j,0s,0n),+0s,2299161j)> 
d2 #=> #<Date: 2015-03-10 ((2457092j,0s,0n),+0s,2299161j)> 

和我们计算有理数:

d2-d1 #=> (9/1) 

其中(因为这将总是整数),我们可以转换为整数:

(9/1).to_i #=> 9 

所以我们得到:

d.map { |d1,d2| (d2-d1).to_i } 
    #=> [9, 5, 12] 

为什么Date#-返回一个有理数而不是整数? @斯蒂芬给出了一个很好的解释here

+0

打我吧。更多的OP可以使用'transaction_dates.map {| transaction | Date.parse(transaction.date)} .each_cons(2).map {| a,b | (b - a).to_i}' – erran

+0

仍然出现错误,我已更新问题以显示阵列中的完整对象的外观,可能是由于问题 – SupremeA

+0

而使问题变得非常好,并且感谢您的详细解释! – SupremeA

0

根据您的日期是否在格式mm-dd-YYYYYYYY-mm-dd(这是你的问题有点暧昧),您可以使用Rails的助手String#to_date转换为Date对象。 (这仅适用于后者。)

a.map { |t| t.date.to_date }.each_cons(2).map { |a, b| (b - a).to_i } 

无论哪种方式,你可能要重构代码,以您的日期存储为您的数据库中正确的日期数据类型。