Search code examples
arraysrubydate-difference

Creating an array of the difference between items in another array


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.


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").)