Instantly share code, notes, and snippets.

campbell/pete_campbell.rbSecret Created Oct 8, 2009

What would you like to do?
 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