secret
Last active

  • Download Gist
pete_campbell.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
require 'time'
 
TWELVE_HOURS = 12*60*60
TWENTYFOUR_HOURS = TWELVE_HOURS*2
 
def average_time_of_day(times)
 
# Since all times are relative, we don't know if the AM times occur before/after the PM times.
# We'll make an assumption that all times are somewhat related and thus should occur at about the
# same time, so we will choose start and end times that create the smallest possible time window.
# To do this, we will calculate the total time range with the AM times occurring before the PM times,
# then we'll compare this to the time range when the AM times occur after the PM times.
#
# If the AM times occur first, then the time window is the maximum PM time minus the minimum AM time.
# If the AM times occur after the PM times, then the time window is the maximum AM time plus 24 hours
# and minus the minimum PM time, eg.
#
# should_we_shift_the_AM_times = ( PM_MAX_TIME - AM_MAX_TIME ) < ( (AM_MIN_TIME+24) - PM_MIN_TIME)
#
# Of course, this only applies if we have both AM and PM times....
midnight = Time.parse('12:00am') # Midnight today, needed since all times are relative
 
# Get each time relative to midnight today (since the input times are relative)
times = times.collect { |t| Time.parse(t)-midnight } # Convert the original array into relative times
am_times, pm_times = times.partition { |t| t < TWELVE_HOURS }
 
# Adjust any AM times by 24 hours if that makes the total time window smaller
if ( !am_times.empty? && !pm_times.empty? && (pm_times.max-am_times.min) > (am_times.max-pm_times.min+24*60*60) )
am_times.each_index { |t| am_times[t] += TWENTYFOUR_HOURS }
times = pm_times + am_times
end
 
# Uncomment the next line to see the times for the selected shortest time window
# print "Debug: Time range: #{Time.at(times.min)+midnight.to_i} to #{Time.at(times.max)+midnight.to_i}\n"
 
# Calculate the average - we must add the relative average time to the baseline midnight time so we can
# get the correct absolute time
sum = times.inject(0) { |s,i| s+i }
average_time = Time.at(sum.to_f/times.length)+midnight.to_i # TO_I needed for time addition operator
 
average_time.strftime('%I:%M%p').downcase
 
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.