# The method assumes that the times given are in order
# of earliest to latest.
# Holds the last DateTime object we looked at to compare with.
# 0 gives us a nice starting point, since a new DateTime
# will always be > 0.
previous_time = 0
average = times.inject(0.0) do |sum, time_as_string|
time = DateTime.strptime(time_as_string, '%I:%M%p')
# If the parsed time happens to be earlier than the last one
# we looked at, loop until we've caught up.
time += 1 while time < previous_time
previous_time = time
# A very simple DateTime => Time conversion, so we can a to_i
sum + Time.parse(time.to_s).to_i
end / times.length
# Should equal 12:01am
puts average_time_of_day(["11:51pm", "11:56pm", "12:01am", "12:06am", "12:11am"])
# Should equal 6:51am
puts average_time_of_day(["6:41am", "6:51am", "7:01am"])
# Works even with times that are a day apart.
# In the following example we'll start at today's date and end
# with a date that's two days from now.
# Should equal 11:35pm
puts average_time_of_day(["6:15am", "12:15pm", "6:15pm", "12:15am", "6:15am", "2:15am"])