My goal is to create an array on integers, each representing the days elapsed between two dates. Eventually I’ll average and do other operations on it.
I’ve reached working code:
require 'date'
dates = ['2020-01-30', '2020-01-24', '2020-01-16'].map { |d| Date.parse(d) }
day_difference = []
dates.each_index do |index|
begin
day_difference.push((dates[index] - dates[index + 1]).to_i)
rescue TypeError # end of array
break
end
end
But I’m wondering if there’s a cleaner way, without having to look out for the last index value. Ruby arrays have a lot of methods, so I wouldn’t be surprised if one of those held a better solution.
require 'date'
dates = ['2020-01-30', '2020-01-24', '2020-01-16']
dates.map { |s| DateTime.strptime(s, '%Y-%m-%d').to_date }.
each_cons(2).map { |d1,d2| (d1-d2).to_i }
#=> [6, 8]
Change (d1-d2)
to (d2-d1)
if desired.
See Enumerable#each_cons.
One could map just once by writing
dates.each_cons(2).map { |s1,s2| (DateTime.strptime(s1, '%Y-%m-%d').to_date -
DateTime.strptime(s2, '%Y-%m-%d').to_date).to_i }
but that has the disadvantage that strptime
must be applied twice to dates.size-2
of the date strings.
Date#parse should only be used (instead of DateTime::strptime
) if one has a high degree of confidence that the date strings will all be in the proper format. (Try
Date.parse("Parse may work or may not work")
.)