Skip to content

Instantly share code, notes, and snippets.

@benwilson512
Created October 31, 2022 18:33
Show Gist options
  • Select an option

  • Save benwilson512/456735775028c2da5bd38572d25b7813 to your computer and use it in GitHub Desktop.

Select an option

Save benwilson512/456735775028c2da5bd38572d25b7813 to your computer and use it in GitHub Desktop.

Revisions

  1. benwilson512 created this gist Oct 31, 2022.
    58 changes: 58 additions & 0 deletions datetime_range_examples.exs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,58 @@
    def intervals_overlap?({%DateTime{}, _} = i1, {%DateTime{}, _} = i2) do
    case {i1, i2} do
    {{_left1, nil}, {_left2, nil}} ->
    true

    {{left1, nil}, {_left2, right2}} ->
    before_inclusive?(left1, right2)

    {{_left1, right1}, {left2, nil}} ->
    before_inclusive?(left2, right1)

    {{left1, right1}, {left2, right2}} ->
    between_inclusive?(left2, left1, right1) or between_inclusive?(left1, left2, right2)
    end
    end

    def disjoint?({%DateTime{} = left1, right1}, {%DateTime{} = left2, right2}) do

    case {right1, right2} do
    {nil, nil} ->
    false

    {%DateTime{}, nil} ->
    DateTime.compare(right1, left2) == :lt

    {nil, %DateTime{}} ->
    DateTime.compare(right2, left1) == :lt

    {%DateTime{}, %DateTime{}} ->
    DateTime.compare(right1, left2) == :lt or
    DateTime.compare(right2, left1) == :lt
    end
    end

    def within_inclusive?(
    {%DateTime{} = inside_left, inside_right},
    {%DateTime{} = outside_left, outside_right}
    ) do
    cond do
    is_nil(inside_right) and is_nil(outside_right) ->
    true

    is_nil(inside_right) or is_nil(outside_right) ->
    before_inclusive?(outside_left, inside_left)

    true ->
    between_inclusive?(inside_left, outside_left, outside_right) &&
    between_inclusive?(inside_right, outside_left, outside_right)
    end
    end

    def between_inclusive?(%DateTime{} = dt, %DateTime{} = left, %DateTime{} = right) do
    before_inclusive?(left, dt) && before_inclusive?(dt, right)
    end

    def before_inclusive?(%DateTime{} = left, %DateTime{} = right) do
    DateTime.compare(left, right) != :gt
    end