# `Calendrical.Kday`

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

# `kday_result`

```elixir
@type kday_result() ::
  Calendar.day() | Date.t() | {:error, :incompatible_calendars | :invalid_date}
```

The result of a k-day computation.

When a k-day function is given a date, the result is a date in the
calendar of that date. When it is given an integer number of ISO
days, the result is an integer number of ISO days. An error tuple
is returned if the result cannot be expressed as a date.

# `first_kday`

```elixir
@spec first_kday(Calendar.day() | Date.t(), Calendrical.day_of_week()) ::
  kday_result()
```

Returns 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()) ::
  kday_result()
```

Returns 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()) ::
  kday_result()
```

Returns 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]

    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()) ::
  kday_result()
```

Returns 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()) ::
  kday_result()
```

Returns 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()) ::
  kday_result()
```

Returns 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()) :: kday_result()
```

Returns 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.

### Examples

    # 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()) ::
  kday_result()
```

Returns 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*
