# `Calendrical.Kday`

Provide K-Day functions for Dates, DateTimes and NaiveDateTimes.

# `first_kday`

```elixir
@spec first_kday(Calendar.day() | Date.t(), Calendrical.day_of_week()) ::
  Calendar.day() | Date.t() | {:error, :incompatible_calendars | :invalid_date}
```

Return the date of the first `day_of_week` on or after the
specified `date`.

## Arguments

* `date` is `t:Calendar.date/0`, a `t:DateTime.t/0`, `t:NaiveDateTime.t/0` or
  ISO days since epoch.

* `k` is an integer day of the week where `1` is
  Monday and `7` is Sunday.

## Returns

* A `t:Calendar.date/0` in the calendar of the date provided as an argument.

## Examples

    # US election day
    iex> Calendrical.Kday.first_kday(~D[2017-11-02], 2)
    ~D[2017-11-07]

    # US Daylight savings end
    iex> Calendrical.Kday.first_kday(~D[2017-11-01], 7)
    ~D[2017-11-05]

# `kday_after`

```elixir
@spec kday_after(Calendar.day() | Date.t(), Calendrical.day_of_week()) ::
  Calendar.day() | Date.t() | {:error, :incompatible_calendars | :invalid_date}
```

Return the date of the `day_of_week` after the
specified `date`.

## Arguments

* `date` is `t:Calendar.date/0`, a `t:DateTime.t/0`, `t:NaiveDateTime.t/0` or
  ISO days since epoch.

* `k` is an integer day of the week where `1` is
  Monday and `7` is Sunday.

## Returns

* A `t:Calendar.date/0` in the calendar of the date provided as an argument.

## Examples

    iex> Calendrical.Kday.kday_after(~D[2016-02-29], 2)
    ~D[2016-03-01]

    iex> Calendrical.Kday.kday_after(~D[2017-11-30], 1)
    ~D[2017-12-04]

    iex> Calendrical.Kday.kday_after(~D[2017-06-30], 6)
    ~D[2017-07-01]

    iex> Calendrical.Kday.kday_after(~D[2021-03-28], 7)
    ~D[2021-04-04]

# `kday_before`

```elixir
@spec kday_before(Calendar.day() | Date.t(), Calendrical.day_of_week()) ::
  Calendar.day() | Date.t() | {:error, :incompatible_calendars | :invalid_date}
```

Return the date of the `day_of_week` before the
specified `date`.

## Arguments

* `date` is `t:Calendar.date/0`, a `t:DateTime.t/0`, `t:NaiveDateTime.t/0` or
  ISO days since epoch.

* `k` is an integer day of the week where `1` is
  Monday and `7` is Sunday.

## Returns

* A `t:Calendar.date/0` in the calendar of the date provided as an argument.

## Examples

    iex> Calendrical.Kday.kday_before(~D[2016-02-29], 2)
    ~D[2016-02-23]

    iex> Calendrical.Kday.kday_before(~D[2017-11-30], 1)
    ~D[2017-11-27]

    iex> Calendrical.Kday.kday_before(~D[2023-09-30], 5)
    ~D[2023-09-29]

    # 6 means Saturday.  Use either the integer value or the atom form.
    iex> Calendrical.Kday.kday_before(~D[2017-06-30], 6)
    ~D[2017-06-24]

# `kday_nearest`

```elixir
@spec kday_nearest(Calendar.day() | Date.t(), Calendrical.day_of_week()) ::
  Calendar.day() | Date.t() | {:error, :incompatible_calendars | :invalid_date}
```

Return the date of the `day_of_week` nearest the
specified `date`.

## Arguments

* `date` is `t:Calendar.date/0`, a `t:DateTime.t/0`, `t:NaiveDateTime.t/0` or
  ISO days since epoch.

* `k` is an integer day of the week where `1` is
  Monday and `7` is Sunday.

## Returns

* A `t:Calendar.date/0` in the calendar of the date provided as an argument.

## Examples

    iex> Calendrical.Kday.kday_nearest(~D[2016-02-29], 2)
    ~D[2016-03-01]

    iex> Calendrical.Kday.kday_nearest(~D[2017-11-30], 1)
    ~D[2017-11-27]

    iex> Calendrical.Kday.kday_nearest(~D[2017-06-30], 6)
    ~D[2017-07-01]

# `kday_on_or_after`

```elixir
@spec kday_on_or_after(Calendar.day() | Date.t(), Calendrical.day_of_week()) ::
  Calendar.day() | Date.t() | {:error, :incompatible_calendars | :invalid_date}
```

Return the date of the `day_of_week` on or after the
specified `date`.

## Arguments

* `date` is `t:Calendar.date/0`, a `t:DateTime.t/0`, `t:NaiveDateTime.t/0` or
  ISO days since epoch.

  * `k` is an integer day of the week where `1` is
  Monday and `7` is Sunday.

## Returns

* A `t:Calendar.date/0` in the calendar of the date provided as an argument

## Examples

    iex> Calendrical.Kday.kday_on_or_after(~D[2016-02-29], 2)
    ~D[2016-03-01]

    iex> Calendrical.Kday.kday_on_or_after(~D[2017-11-30], 1)
    ~D[2017-12-04]

    iex> Calendrical.Kday.kday_on_or_after(~D[2017-06-30], 6)
    ~D[2017-07-01]

    iex> Calendrical.Kday.kday_on_or_after(~D[2023-09-29], 5)
    ~D[2023-09-29]

# `kday_on_or_before`

```elixir
@spec kday_on_or_before(Calendar.day() | Date.t(), Calendrical.day_of_week()) ::
  Calendar.day() | Date.t() | {:error, :incompatible_calendars | :invalid_date}
```

Return the date of the `day_of_week` on or before the
specified `date`.

## Arguments

* `date` is `t:Calendar.date/0`, a `t:DateTime.t/0`, `t:NaiveDateTime.t/0` or
  ISO days since epoch.

  * `k` is an integer day of the week where `1` is
  Monday and `7` is Sunday.

## Returns

* A `t:Calendar.date/0` in the calendar of the date provided as an argument.

## Examples

    iex> Calendrical.Kday.kday_on_or_before(~D[2016-02-29], 2)
    ~D[2016-02-23]

    iex> Calendrical.Kday.kday_on_or_before(~D[2017-11-30], 1)
    ~D[2017-11-27]

    iex> Calendrical.Kday.kday_on_or_before(~D[2017-06-30], 6)
    ~D[2017-06-24]

    iex> Calendrical.Kday.kday_on_or_before(~D[2023-09-29], 5)
    ~D[2023-09-29]

# `last_kday`

```elixir
@spec last_kday(Calendar.day() | Date.t(), Calendrical.day_of_week()) ::
  Calendar.day() | Date.t() | {:error, :incompatible_calendars | :invalid_date}
```

Return the date of the last `day_of_week` on or before the
specified `date`.

## Arguments

* `date` is `t:Calendar.date/0`, a `t:DateTime.t/0`, `t:NaiveDateTime.t/0` or
  ISO days since epoch.

* `k` is an integer day of the week where `1` is
  Monday and `7` is Sunday.

## Returns

* A `t:Calendar.date/0` in the calendar of the date provided as an argument

## Example

    # Memorial Day in the US
    iex> Calendrical.Kday.last_kday(~D[2017-05-31], 1)
    ~D[2017-05-29]

# `nth_kday`

```elixir
@spec nth_kday(Calendar.day() | Date.t(), integer(), Calendrical.day_of_week()) ::
  Calendar.day() | Date.t() | {:error, :incompatible_calendars | :invalid_date}
```

Return the date of the `nth` `day_of_week` on or before/after the
specified `date`.

## Arguments

* `date` is `t:Calendar.date/0`, a `t:DateTime.t/0`, `t:NaiveDateTime.t/0` or
  ISO days since epoch.

* `n` is the cardinal number of `k` before (negative `n`) or after
  (positive `n`) the specified date.

* `k` is an integer day of the week where `1` is
  Monday and `7` is Sunday.

## Returns

* A `t:Calendar.date/0` in the calendar of the date provided as an argument.

## Examples

    # Thanksgiving in the US
    iex> Calendrical.Kday.nth_kday(~D[2017-11-01], 4, 4)
    ~D[2017-11-23]

    # Labor day in the US
    iex> Calendrical.Kday.nth_kday(~D[2017-09-01], 1, 1)
    ~D[2017-09-04]

    # Daylight savings time starts in the US
    iex> Calendrical.Kday.nth_kday(~D[2017-03-01], 2, 7)
    ~D[2017-03-12]

---

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