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

The interface to deal with the implementation of `Tempus.Slot` ordered collection.

Comes with several default implementations, backed up by ordered list of slots,
  by `Stream`, by `AVLTree`¹, and by Year-Month² tree.

### 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{})
    %Tempus.Slots{slots: %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]]

# `container`

```elixir
@type container() :: Enumerable.t(Tempus.Slot.t())
```

# `implementation`

```elixir
@type implementation(group) :: implementation(group, container())
```

# `implementation`

```elixir
@type implementation(group, exact_implementation) :: %{
  __struct__: group,
  slots: exact_implementation
}
```

# `locator`

```elixir
@type locator() ::
  Tempus.Slot.origin() | (Tempus.Slot.t() -&gt; :gt | :eq | :lt | true | false)
```

The type to use in navigation and/or rewinding slots enumerables

# `t`

```elixir
@type t() :: t(Tempus.Slots.Group.t())
```

# `t`

```elixir
@type t(group) :: t(group, implementation(group))
```

# `t`

```elixir
@type t(group, exact_implementation) :: %Tempus.Slots{
  slots: implementation(group, exact_implementation)
}
```

# `add`

Adds another slot to the slots collection.

Joins slots intersecting with the new one, if any.

### Example

    iex> Tempus.Slots.add(%Tempus.Slots{}, Tempus.Slot.wrap(~D|2020-08-07|))
    %Tempus.Slots{slots: %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{}
    ...> |> Tempus.Slots.add(Tempus.Slot.wrap(~D|2020-08-07|))
    ...> |> Tempus.Slots.add(Tempus.Slot.wrap(~D|2020-08-10|))
    ...> |> Tempus.Slots.add(%Tempus.Slot{
    ...>       from: ~U|2020-08-07 01:00:00Z|, to: ~U|2020-08-08 01:00:00Z|})
    %Tempus.Slots{slots: %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}]}}

# `count`

```elixir
@spec count(t()) :: non_neg_integer()
```

Returns the number of slots

### Examples

    iex> import Tempus.Sigils
    iex> slots = [
    ...>   ~I(2000-01-01T00:00:00.000000Z → 2000-01-02T00:00:00.000000Z),
    ...>   ~I(2010-01-01T00:00:00.000000Z → 2010-01-02T00:00:00.000000Z),
    ...>   ~I(2020-01-01T00:00:00.000000Z → 2020-01-02T00:00:00.000000Z)
    ...> ]
    iex> slots |> Tempus.Slots.new() |> Tempus.Slots.count()
    3

# `drop_until`

```elixir
@spec drop_until(t(), locator(), keyword()) :: t()
```

# `inverse`

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

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

### Example

    iex> [
    ...>   Tempus.Slot.wrap(~D|2020-08-07|),
    ...>   Tempus.Slot.wrap(~D|2020-08-08|),
    ...>   Tempus.Slot.wrap(~D|2020-08-10|),
    ...>   Tempus.Slot.wrap(~D|2020-08-12|)
    ...> ] |> Enum.into(%Tempus.Slots{})
    ...> |> Tempus.Slots.inverse()
    %Tempus.Slots{slots: %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{})
    ...> |> Tempus.Slots.inverse()
    %Tempus.Slots{slots: %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(
  slots :: t() | [t()],
  Enumerable.t(Tempus.Slot.t()) | keyword(),
  keyword()
) :: t()
```

Merges many slots into the first element in the list given as an argument.

Other arguments might be enumerables, the first one must be a `Tempus.Slots` instance.

### Examples

    iex> slots = [
    ...>   Tempus.Slot.wrap(~D|2020-08-07|),
    ...>   Tempus.Slot.wrap(~D|2020-08-10|)
    ...> ] |> Enum.into(%Tempus.Slots{})
    %Tempus.Slots{slots: %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},
      %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> 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([slots, other])
    %Tempus.Slots{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.merge([slots, 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`

```elixir
@spec new(implementation :: :list | :data | module(), data :: Enumerable.t()) :: t()
```

Creates an instance of slots, using a backend given as a parameter.

### Examples

    iex> import Tempus.Sigils
    iex> slots = [
    ...>   ~I(2000-01-01T00:00:00.000000Z → 2000-01-02T00:00:00.000000Z),
    ...>   ~I(2010-01-01T00:00:00.000000Z → 2010-01-02T00:00:00.000000Z),
    ...>   ~I(2020-01-01T00:00:00.000000Z → 2020-01-02T00:00:00.000000Z)
    ...> ]
    iex> Tempus.Slots.new([~D|2000-01-01|, ~D|2010-01-01|, ~D|2020-01-01|])
    %Tempus.Slots{slots: Enum.into(slots, Tempus.Slots.List.new())}

# `span`

```elixir
@spec span(t() | [Tempus.Slot.t()], non_neg_integer(), unit :: System.time_unit()) ::
  Enumerable.t()
```

# `take_until`

```elixir
@spec take_until(t(), locator(), keyword()) :: t()
```

# `wrap`
*since 0.3.0* 

```elixir
@spec wrap(
  [Tempus.Slot.origin()] | t(),
  keyword()
) :: t()
```

Wraps the argument into a slots instance. For `nil` it’d be an empty slots.
For everything else it’d call `Slot.wrap/1` on an argument and add it to empty slots.

## Examples

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

---

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