# `Tempo.Holidays.Data`
[🔗](https://github.com/elixir-tempo/tempo_holidays/blob/v0.1.0/lib/tempo/holidays/data.ex#L1)

Load the compiled holiday data, keyed by CLDR territory.

The data is the real [date-holidays](https://github.com/commenthol/date-holidays)
dataset, compiled to `priv/holidays/<CC>.etf` at build time by the `:holidays`
Mix compiler (see `Tempo.Holidays.Build`) and shipped in the package. Loading
it needs no JSON at runtime, so it works on every supported OTP.

`for_territory/2` reads a territory's holidays, or a subdivision's;
`subdivision/2` resolves a subdivision code to the level the data holds it
at; `territories/0` lists the territories that carry data. A territory is
loaded once and kept for the life of the VM.

# `for_territory`

```elixir
@spec for_territory(atom() | String.t(), atom() | String.t() | nil) ::
  {:ok, [Tempo.Holidays.Holiday.t()]} | {:error, {atom(), term()}}
```

Return the compiled holidays for a territory, or one of its subdivisions.

### Arguments

* `territory` is a CLDR territory code as an atom or string, such as `:AU`
  or `"AU"` (case-insensitive).

* `subdivision` is a subdivision code, as `subdivision/2` resolves it, or
  `nil` for the territory's own holidays. The default is `nil`.

### Returns

* `{:ok, [t:Tempo.Holidays.Holiday.t/0]}` — the territory's holidays, with a
  subdivision's own in place of the ones it redefines.

* `{:error, {:unknown_territory, territory}}` for a territory without data
  — including a non-atom, non-string — or an error `subdivision/2` returns,
  so the function never raises on caller input.

### Examples

    iex> {:ok, holidays} = Tempo.Holidays.Data.for_territory(:AU)
    iex> Enum.any?(holidays, &(&1.name == "New Year's Day"))
    true

    iex> Tempo.Holidays.Data.for_territory(:ZZ)
    {:error, {:unknown_territory, :ZZ}}

# `subdivision`

```elixir
@spec subdivision(atom() | String.t(), atom() | String.t() | nil) ::
  {:ok, String.t() | nil} | {:error, {atom(), term()}}
```

Resolve a subdivision code to the subdivision the territory's data holds.

date-holidays keys a territory's data by state and, within a state, by
region. A code names a subdivision at whichever level the data holds it: a
state by its code (`"ENG"`, `"CA"`), a region by its own code when no state
and no other region has it, or by its path from its state (`"CA-LA"`, Los
Angeles, where `"LA"` alone is Louisiana). A leading territory code, as an
ISO 3166-2 code has it (`"GB-ENG"`), is the same subdivision. Codes are
case-insensitive.

### Arguments

* `territory` is a CLDR territory code as an atom or string.

* `subdivision` is a subdivision code as an atom or string, or `nil`.

### Returns

* `{:ok, subdivision}` — the subdivision as the data names it, a state's code
  or a region's path from its state, or `nil` when none was given.

* `{:error, {:unknown_territory, territory}}`,
  `{:error, {:unknown_subdivision, subdivision}}` for a code the data does
  not hold, or `{:error, {:ambiguous_subdivision, subdivision}}` for a region
  code two states share.

### Examples

    iex> Tempo.Holidays.Data.subdivision(:GB, "eng")
    {:ok, "ENG"}

    iex> Tempo.Holidays.Data.subdivision(:US, "CA-LA")
    {:ok, "CA-LA"}

    iex> Tempo.Holidays.Data.subdivision(:US, "LA")
    {:ok, "LA"}

    iex> Tempo.Holidays.Data.subdivision(:GB, "XYZ")
    {:error, {:unknown_subdivision, "XYZ"}}

# `territories`

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

The territories that carry data, as sorted CLDR codes.

### Returns

* A list of CLDR territory codes as strings, such as `["AD", "AE", …]`.

### Examples

    iex> "US" in Tempo.Holidays.Data.territories()
    true

# `version`

```elixir
@spec version() :: {:ok, String.t()} | {:error, :no_data}
```

The date-holidays release the loaded data was built from.

The data is the package's own, built from the release `Tempo.Holidays`
pins, unless `mix tempo.holidays.update --version` has written another
release to the directory `config :tempo_holidays, data_dir: …` names (see
the task's documentation).

### Returns

* `{:ok, version}`, such as `{:ok, "3.38.0"}`, or

* `{:error, :no_data}` when there is no data to load.

### Examples

    iex> {:ok, version} = Tempo.Holidays.Data.version()
    iex> version =~ ~r/^\d+\.\d+\.\d+$/
    true

---

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