我有一个商家的商店营业时间列表,这些营业时间可能会重叠存储在AvailableHours
模型中。该模型将 astart_time
和 aend_time
存储为TimeOfDay
对象(https://github.com/JackC/tod)。
我想遍历列表并比较商店营业时间,以便仅显示 1 个营业时间。例如,如果一家商店可以有几个小时Mon: 9am-2pm
和Mon: 10am-5pm
,我想显示Mon: 9am-5pm
。一家商店也可以在一天内有两次,即Fri: 9-5pm, 7pm-10pm
。我必须在一周中的每一天都这样做。
我遇到的问题是我的代码变得难以管理 - 我开始引入很多嵌套的 if/else 进行手动检查(真是一场噩梦!),但我的问题是:
有没有办法使用 ActiveRecord 生成具有合并时间范围的哈希?
def ranges_overlap?(shift, current_shift)
shift.include?(current_shift.beginning) || current_shift.include?(shift.beginning)
end
def merge_ranges(shift, current_shift)
new_open_time = [shift.beginning, current_shift.beginning].min
new_close_time = [shift.ending, current_shift.ending].max
Shift.new(new_open_time, new_close_time)
end
def get_aggregate_merchant_hours
merchant = self
day = nil
shifts_array = []
output_shift_array = []
merchant_shifts = merchant_shifts = merchant.available_hours.order(day: :asc, open_time: :desc).map do |ah|
merged_shift = nil
show_output = false
# if it's a new day
if day.blank? || day != ah.day
output_shift_array = shifts_array
shifts_array = []
show_output = true if !day.blank?
output_day = day
day = ah.day
end
next if ah.open_time.blank? || ah.close_time.blank?
open_time = ah.open_time
close_time = ah.close_time
current_shift = Shift.new(open_time, close_time)
if !shifts_array.blank?
#compare and merge
shifts_array.each do |shift|
merged_shift = merge_ranges(shift, current_shift) if ranges_overlap?(shift, current_shift)
end
end
#replace old shift with merged shift
if merged_shift
delete_shift = shifts_array.find(beginning: current_shift.beginning, ending: current_shift.ending).first
shifts_array.delete(delete_shift) if delete_shift
shifts_array.push(merged_shift)
else
shifts_array.push(current_shift)
end
if show_output
store_hours_string = ""
if output_shift_array.blank?
store_hours_string = "Closed"
else
output_shift_array.each do |shift|
shift.beginning.strftime("%I:%M%p")
shift.ending.strftime("%I:%M%p")
if store_hours_string.blank?
store_hours_string << "#{shift.beginning.strftime("%I:%M%p").downcase} - #{shift.ending.strftime("%I:%M%p").downcase}"
else
store_hours_string << ", #{shift.beginning.strftime("%I:%M%p").downcase} - #{shift.ending.strftime("%I:%M%p").downcase}"
end
end
end
"#{Date::DAYNAMES[output_day][0..2]}: #{store_hours_string}"
end
end
#output last shift
store_hours_string = ""
if output_shift_array.blank?
store_hours_string = "Closed"
else
output_shift_array.each do |shift|
shift.beginning.strftime("%I:%M%p")
shift.ending.strftime("%I:%M%p")
if store_hours_string.blank?
store_hours_string << "#{shift.beginning.strftime("%I:%M%p").downcase} - #{shift.ending.strftime("%I:%M%p").downcase}"
else
store_hours_string << ", #{shift.beginning.strftime("%I:%M%p").downcase} - #{shift.ending.strftime("%I:%M%p").downcase}"
end
end
end
merchant_shifts << "#{Date::DAYNAMES[day][0..2]}: #{store_hours_string}"
merchant_shifts.compact
end