For future reference, I’ve adapted Greg’s solution with time being converted to seconds using Time.to_seconds_after_midnight/1
, i.e. it works with precision to seconds:
classes = [
%{id: 1, time: Time.new!(15,00,00), duration: 60}, #
%{id: 2, time: Time.new!(16,00,00), duration: 180}, # overlap: true
%{id: 3, time: Time.new!(17,00,00), duration: 60}, # overlap: true
%{id: 4, time: Time.new!(18,00,00), duration: 60}, # overlap: true
%{id: 5, time: Time.new!(19,00,00), duration: 60}, #
%{id: 6, time: Time.new!(20,00,00), duration: 120}, # overlap: true
%{id: 7, time: Time.new!(21,00,00), duration: 60}, # overlap: true
]
ranges =
Map.new(classes, fn %{time: t, duration: d, id: id} ->
{tsec, _} = Time.to_seconds_after_midnight(t)
{id, tsec..(tsec + (d * 60) - 1)}
end)
Enum.map(classes, fn c ->
if Enum.all?(classes -- [c], &Range.disjoint?(ranges[c.id], ranges[&1.id])) do
c
else
Map.put(c, :overlap, true)
end
end)
|> IO.inspect