# `Tempo.TimeZoneDatabase`
[🔗](https://github.com/elixir-tempo/tempo/blob/v1.6.4/lib/tempo/time_zone_database.ex#L1)

Access to the time zone database Tempo uses for zone validation,
offset resolution, and DST-aware arithmetic.

Tempo is **time zone database agnostic**: it works against the
standard `Calendar.TimeZoneDatabase` behaviour rather than any
specific implementation. The database is resolved, in order, from:

1. The `:ex_tempo, :time_zone_database` application environment.

2. Elixir's own configured database, `Calendar.get_time_zone_database/0`
   (set with `config :elixir, :time_zone_database, ...` or
   `Calendar.put_time_zone_database/1`).

Any implementation works — [`tz`](https://hex.pm/packages/tz),
[`tzdata`](https://hex.pm/packages/tzdata),
[`time_zone_info`](https://hex.pm/packages/time_zone_info), or
[`zoneinfo`](https://hex.pm/packages/zoneinfo). Configure one at
boot, for example:

    config :elixir, :time_zone_database, Tz.TimeZoneDatabase

When no database is configured (Elixir's default is
`Calendar.UTCOnlyTimeZoneDatabase`), parsing remains fully
functional: zone names in IXDTF suffixes are accepted without
registry validation, and only the operations that genuinely need
zone rules — UTC projection, `shift_zone/2`, DST-aware walks —
degrade or error.

# `period`

```elixir
@type period() :: Calendar.TimeZoneDatabase.time_zone_period()
```

A time zone period as returned by the `Calendar.TimeZoneDatabase`
behaviour — at minimum `:utc_offset`, `:std_offset`, and
`:zone_abbr`.

# `database`

```elixir
@spec database() :: Calendar.time_zone_database()
```

The `Calendar.TimeZoneDatabase` implementation Tempo resolves for
this call — see the module doc for the resolution order.

### Returns

* A module implementing `Calendar.TimeZoneDatabase`.

# `period_at_utc`

```elixir
@spec period_at_utc(String.t(), integer()) :: {:ok, period()} | {:error, term()}
```

The period in effect in `zone` at a UTC instant given as gregorian
seconds (seconds since year 0, `:calendar`'s epoch).

Pre-common-era instants return a zero-offset local-mean-time
period without consulting the database.

### Arguments

* `zone` is an IANA zone name.

* `utc_seconds` is the instant in gregorian seconds, UTC.

### Returns

* `{:ok, period}` — a UTC instant is never ambiguous.

* `{:error, reason}` from the database (unknown zone, or no real
  database configured).

# `period_at_wall`

```elixir
@spec period_at_wall(String.t(), integer()) ::
  {:ok, period()}
  | {:ambiguous, period(), period()}
  | {:gap, {period(), Calendar.naive_datetime()},
     {period(), Calendar.naive_datetime()}}
  | {:error, term()}
```

The period(s) matching a wall-clock reading in `zone`, given as
gregorian seconds.

Returns the standard behaviour shapes: `{:ok, period}` for an
unambiguous reading, `{:ambiguous, first, second}` for a DST
fall-back, `{:gap, ...}` for a spring-forward reading that does
not exist, or `{:error, reason}`. Pre-common-era readings return
`{:ok, local-mean-time}` without consulting the database.

### Arguments

* `zone` is an IANA zone name.

* `wall_seconds` is the wall-clock reading in gregorian seconds.

### Returns

* `{:ok, period}` | `{:ambiguous, period, period}` |
  `{:gap, {period, limit}, {period, limit}}` | `{:error, reason}`.

# `total_offset`

```elixir
@spec total_offset(period()) :: number()
```

The total UTC offset of a period in seconds — the standard offset
plus any daylight-saving adjustment.

### Arguments

* `period` is a `t:period/0`.

### Returns

* An offset in seconds. Always an integer in practice; the spec is
  `number()` because the behaviour's period field specs admit floats.

# `zone_exists?`

```elixir
@spec zone_exists?(String.t()) :: boolean()
```

Return whether `zone` is a time zone known to the configured
database.

When no real database is configured (the resolver answers with
Elixir's UTC-only default), any syntactically valid zone name is
accepted — parsing must not depend on zone data being present;
operations that need the zone's rules surface their own errors.

### Arguments

* `zone` is an IANA zone name (`"Europe/Paris"`, …).

### Returns

* `true` or `false`.

---

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