# `Koyomi.Holidays`
[🔗](https://github.com/hattoriai/koyomi/blob/v0.2.1/lib/koyomi/holidays.ex#L1)

Public holidays, computed by rule, for the pickers to mark days.

    Koyomi.Holidays.list("PT", 2027)
    #=> [%Koyomi.Holiday{date: ~D[2027-01-01], name: "Ano Novo", english: "New Year's Day", country: "PT"}, ...]

    range = Date.range(~D[2027-12-01], ~D[2028-01-31])
    Koyomi.Holidays.to_client(["PT", "GB"], range, "pt-PT")
    #=> %{"2027-12-25" => "Natal · Christmas Day", ...}

A source of holidays is a country code (see `countries/0`, in any case)
or a module that implements `Koyomi.Holidays.Provider`, for the
holidays of a region or the days a business is closed. Each built-in
country is such a module too, such as `Koyomi.Holidays.PT`.

## What is listed

The national public holidays: the days off that the law gives in the
whole country. Regional, local and religious days that only some
people keep are not listed, nor are days off by custom (such as
Christmas Eve in many countries). The module of each country says what
it keeps and leaves out, for example `Koyomi.Holidays.CH` for
Switzerland, where the cantons set the holidays.

The rules are those in force in 2026. A holiday that began or ended
since 2010 is listed only in the years it was kept (Juneteenth in the
United States from 2021). Older changes are not followed: earlier years
follow the rules of 2010. One-off holidays (a coronation, a jubilee)
are not listed.

Each holiday has a `name` in the main language of its country and an
`english` name. A few countries have several official languages; their
module names the language chosen: English for Canada, Dutch for
Belgium, German for Switzerland, Finnish for Finland, Hindi for India,
English for Ireland and South Africa.

## Weekends

Where the law gives another day off when a holiday falls on a weekend
(substitute days in the United Kingdom, 振替休日 in Japan, observed days
in the United States, Mondayisation in Australia and New Zealand), the
holiday stays on its date and a second entry marks the day off, such as
"Christmas Day (substitute day)". Where the law moves the holiday
itself (Argentina's movable holidays), only the day it moves to is
listed.

# `source`

```elixir
@type source() :: String.t() | module()
```

A country code, such as "PT", or a `Koyomi.Holidays.Provider` module.

# `between`

```elixir
@spec between(source() | [source()], Date.Range.t()) :: [Koyomi.Holiday.t()]
```

Returns the holidays of one source or a list of sources within `range`,
across years, sorted by date. Holidays on the same day keep the order
of the sources.

## Examples

    iex> range = Date.range(~D[2027-12-24], ~D[2028-01-01])
    iex> for holiday <- Koyomi.Holidays.between(["PT", "DE"], range),
    ...>     do: {holiday.date, holiday.name}
    [
      {~D[2027-12-25], "Natal"},
      {~D[2027-12-25], "1. Weihnachtstag"},
      {~D[2027-12-26], "2. Weihnachtstag"},
      {~D[2028-01-01], "Ano Novo"},
      {~D[2028-01-01], "Neujahr"}
    ]

# `countries`

```elixir
@spec countries() :: [String.t()]
```

Returns the codes of the countries with built-in holidays (ISO 3166-1
alpha-2), sorted.

## Examples

    iex> "JP" in Koyomi.Holidays.countries()
    true

# `list`

```elixir
@spec list(source(), integer()) :: [Koyomi.Holiday.t()]
```

Returns the holidays of a source in `year`, sorted by date. Holidays on
the same day keep the order of the source.

Raises `ArgumentError` for an unknown country code, a module that is
not a provider, or a provider that returns entries of another shape.

## Examples

    iex> [first | _] = Koyomi.Holidays.list("pt", 2027)
    iex> {first.date, first.name, first.english, first.country}
    {~D[2027-01-01], "Ano Novo", "New Year's Day", "PT"}

# `to_client`

```elixir
@spec to_client(source() | [source()], Date.Range.t(), String.t()) :: %{
  required(String.t()) =&gt; String.t()
}
```

Returns the holidays within `range` as a map from ISO 8601 date to
name, for the picker in the browser.

A holiday has its `name` when the language of `locale` (such as "pt" in
"pt-PT" or "pt_BR") is the language of its country, and its `english`
name otherwise. "no" and "nn" count as Norwegian Bokmål ("nb"). The
holidays of a provider without `language/0` always have their `name`.
Several holidays on one day are joined with " · ", without repeats.

## Examples

    iex> range = Date.range(~D[2027-12-25], ~D[2027-12-25])
    iex> Koyomi.Holidays.to_client(["PT", "DE"], range, "pt-PT")
    %{"2027-12-25" => "Natal · Christmas Day"}

---

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