defmodule DateTimeNilInfinity do @moduledoc false # Like `DateTime` except `nil` is considered positive infinity def compare(%DateTime{}, nil), do: :lt def compare(nil, %DateTime{}), do: :gt def compare(%DateTime{} = a, %DateTime{} = b), do: DateTime.compare(a, b) end defmodule DateTimeInterval do @moduledoc false import CompareChain, only: [compare?: 2] defmacrop dt?(expr), do: quote(do: compare?(unquote(expr), DateTimeNilInfinity)) def disjoint?({left1, right1}, {left2, right2}) do dt?(right1 < left2 or right2 < left1) end def overlaps?(a, b) do not disjoint?(a, b) end def within_inclusive?({inside_left, inside_right}, {outside_left, outside_right}) do dt?(outside_left <= inside_left and inside_right <= outside_right) end end