# `Calendrical.TimeZone`

Resolve textual time-zone identifiers captured by the
parser into UTC offsets.

The resolver tries these strategies in order:

1. ISO 8601 offset — `Z`, `±HHMM`, `±HH:MM`, `±HH:MM:SS`.

2. GMT/UTC format — `GMT`, `GMT+10`, `UTC-5:30`.

3. IANA region/city — `Asia/Tokyo`, `America/New_York`.
   Looked up via the host application's installed time-zone
   database (`Tzdata` or `Tz`) — whichever is loaded at
   runtime. If neither is loaded, IANA names are rejected
   (consumer should add `:tzdata` or `:tz` as a dependency
   to support them).

4. Short abbreviation — `PST`, `EST`, `JST`. Resolved via a
   small static table for the most common abbreviations.
   Note that abbreviations are inherently ambiguous (CST
   could be Central or China Standard); the table picks
   the most common North-American/Asian/European reading.

5. CLDR locale name — `Pacific Time`, `Greenwich Mean Time`.
   Looked up via `Localize`'s CLDR `timeZoneNames` data for
   the parsing locale. Zone-specific names are tried first,
   then metazone names (`Pacific Standard Time`,
   `Mitteleuropäische Zeit`), which cover most localized
   zone names in CLDR. A metazone resolves to its
   representative zone for the locale's territory —
   `Mitteleuropäische Zeit` under a `:de` locale is
   `Europe/Berlin` — falling back to the metazone's golden
   zone (`Europe/Paris`).

When the parser captures a wall-clock instant alongside an
IANA zone, the resolver uses the instant to pick between
standard / daylight offsets (e.g. `2024-07-15 14:00 America/New_York`
→ `EDT (-04:00)`, while `2024-01-15 14:00 America/New_York`
→ `EST (-05:00)`).

# `resolve`

```elixir
@spec resolve(String.t(), NaiveDateTime.t(), Keyword.t()) ::
  {:ok, DateTime.t()} | {:error, atom() | Exception.t()}
```

Resolves `zone_string` against a wall-clock `NaiveDateTime`.

### Arguments

* `zone_string` is the captured zone token (e.g. `"PST"`,
  `"+0530"`, `"Asia/Tokyo"`, `"Pacific Time"`).

* `naive_dt` is the parsed wall-clock instant. Used to
  disambiguate standard vs daylight offsets for IANA
  zones (e.g. `America/New_York` is `-05:00` in January
  and `-04:00` in July).

* `options` is a keyword list of options.

### Options

* `:locale` — locale to use when looking up CLDR-style
  names like `"Pacific Time"`. Defaults to
  `Localize.get_locale/0`.

### Returns

* `{:ok, DateTime.t()}` when the zone resolves.

* `{:error, reason}` when the zone string isn't
  recognizable.

### Examples

    iex> {:ok, datetime} = Calendrical.TimeZone.resolve("+05:30", ~N[2024-07-15 14:00:00])
    iex> to_string(datetime)
    "2024-07-15 14:00:00+05:30"

    iex> {:ok, datetime} = Calendrical.TimeZone.resolve("GMT+02:00", ~N[2024-01-15 09:00:00])
    iex> to_string(datetime)
    "2024-01-15 09:00:00+02:00"

    iex> {:ok, datetime} = Calendrical.TimeZone.resolve("Asia/Tokyo", ~N[2024-07-15 14:00:00])
    iex> {datetime.zone_abbr, datetime.utc_offset}
    {"JST", 32400}

    iex> {:ok, datetime} = Calendrical.TimeZone.resolve("Pacific Standard Time", ~N[2024-07-15 14:00:00])
    iex> datetime.time_zone
    "America/Los_Angeles"

    iex> {:ok, datetime} = Calendrical.TimeZone.resolve("Mitteleuropäische Zeit", ~N[2024-07-15 14:00:00], locale: :de)
    iex> datetime.time_zone
    "Europe/Berlin"

    iex> Calendrical.TimeZone.resolve("Middle Earth Time", ~N[2024-07-15 14:00:00])
    {:error, :unresolvable_zone}

# `tz_database`

```elixir
@spec tz_database() :: module() | nil
```

Returns the time-zone database module, or `nil` when none is
configured and no known implementation is loaded.

The database resolves, in order, from:

1. The `:elixir` `:time_zone_database` application environment
   (`config :elixir, :time_zone_database, Tz.TimeZoneDatabase`) —
   Elixir's own UTC-only default is treated as "not configured".

2. Tz.TimeZoneDatabase or `Tzdata.TimeZoneDatabase` when the
   respective library is loaded (Tz is preferred when both are
   available).

Consumers that want IANA name resolution should add a
`Calendar.TimeZoneDatabase` implementation to their dependency
list and configure it. The resolver works without one but
rejects IANA names.

### Returns

* A module implementing `Calendar.TimeZoneDatabase`, or

* `nil` when nothing is configured and neither known library
  is loaded.

### Examples

    iex> Calendrical.TimeZone.tz_database()
    Tz.TimeZoneDatabase

---

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