# `Tempus.Slots.List`
[🔗](https://github.com/am-kantox/tempus/blob/v1.0.0-rc.0/lib/tempus/slots/list.ex#L1)

The default `List` implementation of `Tempus.Slots` ordered collection.

### Examples

    iex> slots = [
    ...>   Tempus.Slot.wrap(~D|2020-08-07|),
    ...>   Tempus.Slot.wrap(~D|2020-08-10|),
    ...>   %Tempus.Slot{
    ...>       from: ~U|2020-08-07 01:00:00Z|, to: ~U|2020-08-08 01:00:00Z|}]
    ...> Enum.into(slots, %Tempus.Slots.List{})
    %Tempus.Slots.List{slots: [
      %Tempus.Slot{from: ~U[2020-08-07 00:00:00.000000Z], to: ~U[2020-08-08 01:00:00Z], from_open: false, to_open: true},
      %Tempus.Slot{from: ~U[2020-08-10 00:00:00.000000Z], to: ~U[2020-08-11 00:00:00.000000Z], from_open: false, to_open: true}]}
    iex> Enum.map(slots, & &1.from)
    [~U[2020-08-07 00:00:00.000000Z], ~U[2020-08-10 00:00:00.000000Z], ~U[2020-08-07 01:00:00Z]]

# `t`

```elixir
@type t() :: Tempus.Slots.implementation(Tempus.Slots.List, [Tempus.Slot.t()])
```

# `add`

```elixir
@spec add(t(), Tempus.Slot.origin(), keyword()) :: t()
```

Adds another slot to the slots collection implemented as list.

Joins slots intersecting with the new one, if any.

### Example

    iex> Tempus.Slots.List.add(%Tempus.Slots.List{}, Tempus.Slot.wrap(~D|2020-08-07|))
    %Tempus.Slots.List{slots: [
      %Tempus.Slot{from: ~U[2020-08-07 00:00:00.000000Z], to: ~U[2020-08-08 00:00:00.000000Z], from_open: false, to_open: true}]}

    iex> %Tempus.Slots.List{}
    ...> |> Tempus.Slots.List.add(Tempus.Slot.wrap(~D|2020-08-07|))
    ...> |> Tempus.Slots.List.add(Tempus.Slot.wrap(~D|2020-08-10|))
    ...> |> Tempus.Slots.List.add(%Tempus.Slot{
    ...>       from: ~U|2020-08-07 01:00:00Z|, to: ~U|2020-08-08 01:00:00Z|})
    %Tempus.Slots.List{slots: [
      %Tempus.Slot{from: ~U[2020-08-07 00:00:00.000000Z], to: ~U[2020-08-08 01:00:00Z], from_open: false, to_open: true},
      %Tempus.Slot{from: ~U[2020-08-10 00:00:00.000000Z], to: ~U[2020-08-11 00:00:00.000000Z], from_open: false, to_open: true}]}

# `inverse`

```elixir
@spec inverse(
  t(),
  keyword()
) :: t()
```

Inverses `Slots` returning the new `Slots` instance with slots set where
  there were blanks.

### Example

    iex> [~D|2020-08-07|, ~D|2020-08-08|, ~D|2020-08-10|, ~D|2020-08-12|]
    ...> |> Enum.into(%Tempus.Slots.List{})
    ...> |> Tempus.Slots.List.inverse()
    %Tempus.Slots.List{slots: [
      %Tempus.Slot{from: nil, to: ~U[2020-08-07 00:00:00.000000Z], from_open: true, to_open: true},
      %Tempus.Slot{from: ~U[2020-08-09 00:00:00.000000Z], to: ~U[2020-08-10 00:00:00.000000Z], from_open: false, to_open: true},
      %Tempus.Slot{from: ~U[2020-08-11 00:00:00.000000Z], to: ~U[2020-08-12 00:00:00.000000Z], from_open: false, to_open: true},
      %Tempus.Slot{from: ~U[2020-08-13 00:00:00.000000Z], to: nil, from_open: false, to_open: true}]}

    iex> [
    ...>   %Tempus.Slot{to: ~U[2020-08-09 00:00:00.000000Z], from_open: false, to_open: true},
    ...>   Tempus.Slot.wrap(~D|2020-08-10|),
    ...>   %Tempus.Slot{from: ~U[2020-08-12 00:00:00.000000Z], from_open: false, to_open: true}
    ...> ] |> Enum.into(%Tempus.Slots.List{})
    ...> |> Tempus.Slots.List.inverse()
    %Tempus.Slots.List{slots: [
      %Tempus.Slot{from: ~U[2020-08-09 00:00:00.000000Z], to: ~U[2020-08-10 00:00:00.000000Z], from_open: false, to_open: true},
      %Tempus.Slot{from: ~U[2020-08-11 00:00:00.000000Z], to: ~U[2020-08-12 00:00:00.000000Z], from_open: false, to_open: true}
    ]}

# `merge`

```elixir
@spec merge(t(), t() | Tempus.Slots.Stream.t(), keyword()) :: t()
```

Merges `other` into `this` slots instance. `other` might be `Enum` _or_ `Stream`.
When `other` is a stream, it gets terminated immediately after the last element
in `this`.

### Examples

    iex> slots = [
    ...>   Tempus.Slot.wrap(~D|2020-08-07|),
    ...>   Tempus.Slot.wrap(~D|2020-08-10|)
    ...> ] |> Enum.into(%Tempus.Slots.List{})
    iex> other = [
    ...>   %Tempus.Slot{from: ~U|2020-08-07 23:00:00Z|, to: ~U|2020-08-08 12:00:00Z|},
    ...>   %Tempus.Slot{from: ~U|2020-08-12 23:00:00Z|, to: ~U|2020-08-12 23:30:00Z|}
    ...> ]
    iex> Tempus.Slots.merge([%Tempus.Slots{slots: slots}, other]).slots
    %Tempus.Slots.List{slots: [
      %Tempus.Slot{from: ~U[2020-08-07 00:00:00.000000Z], to: ~U[2020-08-08 12:00:00Z], from_open: false, to_open: true},
      %Tempus.Slot{from: ~U[2020-08-10 00:00:00.000000Z], to: ~U[2020-08-11 00:00:00.000000Z], from_open: false, to_open: true},
      %Tempus.Slot{from: ~U[2020-08-12 23:00:00Z], to: ~U[2020-08-12 23:30:00Z], from_open: false, to_open: true}]}
    iex> %Tempus.Slots{slots: slots} |> Tempus.Slots.merge(Tempus.Slots.wrap(other, Tempus.Slots.Stream)) |> Enum.to_list()
    [
      %Tempus.Slot{from: ~U[2020-08-07 00:00:00.000000Z], to: ~U[2020-08-08 12:00:00Z], from_open: false, to_open: true},
      %Tempus.Slot{from: ~U[2020-08-10 00:00:00.000000Z], to: ~U[2020-08-11 00:00:00.000000Z], from_open: false, to_open: true},
      %Tempus.Slot{from: ~U[2020-08-12 23:00:00Z], to: ~U[2020-08-12 23:30:00Z], from_open: false, to_open: true}]

# `new`

Creates the new instance of `Tempus.Slots.List` struct. One usually does not need to call this function directly.

# `split`

```elixir
@spec split(t(), Tempus.Slots.locator(), keyword()) ::
  {[Tempus.Slot.t()], [Tempus.Slot.t()]}
```

Splits the slots by the pivot given as a `Slot.t` or as a function.

To keep it consistent, the function actually does _split it until_,
which is intuitive when the pivot is given and kinda counter-intuitive
when the _locator_ function is given.

See the examples below to grasp the reasoning behind this
architectural decision.

### Examples

    iex> import Tempus.Guards
    ...> import Tempus.Sigils
    ...> slots =
    ...> [~D|2020-08-07|, ~D|2020-08-08|, ~D|2020-08-10|, ~D|2020-08-12|]
    ...> |> Enum.into(%Tempus.Slots.List{})
    iex> slots |> Tempus.Slots.List.split(~U|2020-08-09T12:00:00Z|)
    {
      [%Tempus.Slot{from: ~U[2020-08-07 00:00:00.000000Z], to: ~U[2020-08-08 00:00:00.000000Z], from_open: false, to_open: true}, %Tempus.Slot{from: ~U[2020-08-08 00:00:00.000000Z], to: ~U[2020-08-09 00:00:00.000000Z], from_open: false, to_open: true}],
      [%Tempus.Slot{from: ~U[2020-08-10 00:00:00.000000Z], to: ~U[2020-08-11 00:00:00.000000Z], from_open: false, to_open: true}, %Tempus.Slot{from: ~U[2020-08-12 00:00:00.000000Z], to: ~U[2020-08-13 00:00:00.000000Z], from_open: false, to_open: true}]
    }
    iex> slots |> Tempus.Slots.List.split(&is_slot_coming_before(Tempus.Slot.wrap(~U|2020-08-09T12:00:00Z|), &1))
    {
      [%Tempus.Slot{from: ~U[2020-08-07 00:00:00.000000Z], to: ~U[2020-08-08 00:00:00.000000Z], from_open: false, to_open: true}, %Tempus.Slot{from: ~U[2020-08-08 00:00:00.000000Z], to: ~U[2020-08-09 00:00:00.000000Z], from_open: false, to_open: true}],
      [%Tempus.Slot{from: ~U[2020-08-10 00:00:00.000000Z], to: ~U[2020-08-11 00:00:00.000000Z], from_open: false, to_open: true}, %Tempus.Slot{from: ~U[2020-08-12 00:00:00.000000Z], to: ~U[2020-08-13 00:00:00.000000Z], from_open: false, to_open: true}]
    }

---

*Consult [api-reference.md](api-reference.md) for complete listing*
