# `Localize.DateTime.Timezone`
[🔗](https://github.com/elixir-localize/localize/blob/v0.50.0/lib/localize/datetime/timezone.ex#L1)

Provides timezone data access and timezone formatting for CLDR
date/time format symbols.

This module combines CLDR short zone code lookups (mapping between
BCP 47 timezone identifiers and IANA timezone names) with the format
symbol handlers for `z`, `Z`, `O`, `v`, `V`, `X`, and `x`.

# `fetch_short_zone`

```elixir
@spec fetch_short_zone(String.t()) :: {:ok, map()} | {:error, Exception.t()}
```

Returns `{:ok, map}` for a given CLDR short zone code,
or `:error` if no such short code exists.

### Arguments

* `short_zone` is a CLDR short timezone code string.

### Returns

* `{:ok, map}` where map has `:aliases`, `:preferred`, and
  `:territory` keys.

* `{:error, exception}` if the short zone code is not found.

### Examples

    iex> Localize.DateTime.Timezone.fetch_short_zone("ausyd")
    {
      :ok,
      %{
        preferred: nil,
        aliases: ["Australia/Sydney", "Australia/ACT", "Australia/Canberra", "Australia/NSW"],
        territory: :AU
      }
    }

    iex> match?({:error, _}, Localize.DateTime.Timezone.fetch_short_zone("nope"))
    true

# `get_short_zone`

```elixir
@spec get_short_zone(String.t(), term()) :: map() | term()
```

Returns a timezone map for a given CLDR short zone code,
or a default value.

### Arguments

* `short_zone` is a CLDR short timezone code string.

* `default` is the value to return if the short zone is not
  found. Defaults to `nil`.

### Returns

* A map with `:aliases`, `:preferred`, and `:territory` keys,
  or the default value.

### Examples

    iex> Localize.DateTime.Timezone.get_short_zone("ausyd")
    %{
      preferred: nil,
      aliases: ["Australia/Sydney", "Australia/ACT", "Australia/Canberra", "Australia/NSW"],
      territory: :AU
    }

    iex> Localize.DateTime.Timezone.get_short_zone("nope")
    nil

# `gmt_format`

```elixir
@spec gmt_format(map(), atom(), Keyword.t()) ::
  {:ok, String.t()} | {:error, Exception.t()}
```

Returns the localized GMT offset format.

Uses the locale's `gmt_format` pattern (e.g., `["GMT", 0]`) and
`hour_format` pattern to render the datetime's total UTC offset.

### Arguments

* `datetime` is a map with an integer `:utc_offset` in seconds
  and optionally an integer `:std_offset` in seconds (a
  `t:DateTime.t/0` satisfies this shape).

* `locale_id` is a **resolved** locale identifier atom (e.g., `:en`),
  such as the `cldr_locale_id` of a validated
  `t:Localize.LanguageTag.t/0`. It is passed directly to
  `Localize.Locale.get/2` and is not validated or canonicalized
  by this function.

* `options` is a keyword list of options.

### Options

* `:format` is `:long` (e.g., `"GMT+01:00"`) or `:short` (e.g.,
  `"GMT+1"`; minutes are dropped when zero). The default is
  `:long`.

* `:zero_format` controls rendering of a zero offset. The default,
  `:gmt_zero`, uses the locale's zero pattern (e.g., `"GMT"`); any
  other value formats the zero offset through the hour pattern
  (e.g., `"GMT+00:00"`).

### Returns

* `{:ok, formatted_string}` (e.g., `"GMT+01:00"` or `"GMT"`).

* `{:error, exception}` if the locale's timezone data cannot be
  loaded.

### Examples

    iex> Localize.DateTime.Timezone.gmt_format(%{utc_offset: 3600, std_offset: 0}, :en)
    {:ok, "GMT+01:00"}

    iex> Localize.DateTime.Timezone.gmt_format(%{utc_offset: -28800, std_offset: 0}, :en, format: :short)
    {:ok, "GMT-8"}

# `iso_format`

```elixir
@spec iso_format(map(), Keyword.t()) :: {:ok, String.t()}
```

Returns the ISO 8601 timezone offset format.

This function is locale-independent — ISO 8601 offsets are the
same in every locale.

### Arguments

* `datetime` is a map with an integer `:utc_offset` in seconds
  and optionally an integer `:std_offset` in seconds (a
  `t:DateTime.t/0` satisfies this shape).

* `options` is a keyword list of options.

### Options

* `:format` is `:short` (minutes omitted when zero), `:long`
  (hours and minutes), or `:full` (like `:long`, with seconds
  appended when non-zero). The default is `:long`.

* `:type` is `:basic` (no separator, e.g., `"+0500"`) or
  `:extended` (colon separator, e.g., `"+05:00"`). The default
  is `:basic`.

* `:z_for_zero` is a boolean controlling whether a zero offset
  renders as `"Z"`. The default is `true`.

### Returns

* `{:ok, formatted_string}` (e.g., `"+0500"`, `"Z"`, `"+05:00"`).

### Examples

    iex> Localize.DateTime.Timezone.iso_format(%{utc_offset: 18000, std_offset: 0})
    {:ok, "+0500"}

    iex> Localize.DateTime.Timezone.iso_format(%{utc_offset: 19800, std_offset: 0}, type: :extended)
    {:ok, "+05:30"}

    iex> Localize.DateTime.Timezone.iso_format(%{utc_offset: 0, std_offset: 0})
    {:ok, "Z"}

# `metazone_for`

```elixir
@spec metazone_for(String.t(), map() | nil) :: atom() | nil
```

Returns the CLDR metazone for an IANA timezone name.

Zones move between metazones over time (for example
`America/Indiana/Knox` has alternated between the central and
eastern metazones), so the datetime selects the applicable usage
period.

### Arguments

* `time_zone` is an IANA timezone name (e.g., `"America/New_York"`)
  or any of its CLDR aliases (e.g., `"Asia/Calcutta"`).

* `datetime` is a map that may carry `:year` .. `:second` fields
  selecting the metazone in effect at that instant. When the fields
  are absent (or `datetime` is `nil`), the currently effective
  metazone is returned. The default is `nil`.

### Returns

* The metazone as an atom (e.g., `:america_eastern`), matching the
  keys of the locale `time_zone_names.metazone` data.

* `nil` when the zone has no metazone mapping for the instant.

### Examples

    iex> Localize.DateTime.Timezone.metazone_for("America/New_York")
    :america_eastern

    iex> Localize.DateTime.Timezone.metazone_for("Asia/Calcutta")
    :india

    iex> Localize.DateTime.Timezone.metazone_for("America/Indiana/Knox", ~N[2000-06-01 00:00:00])
    :america_eastern

    iex> Localize.DateTime.Timezone.metazone_for("America/Indiana/Knox", ~N[2020-06-01 00:00:00])
    :america_central

# `non_location_format`

```elixir
@spec non_location_format(map(), atom(), Keyword.t()) ::
  {:ok, String.t()} | {:error, Exception.t()}
```

Returns the specific or generic non-location timezone name.

Looks up the zone's own name, then its metazone name, in the
locale's timezone data (e.g., "Eastern Standard Time"). When the
locale carries neither, falls back to `gmt_format/3`.

### Arguments

* `datetime` is a map with `:time_zone`, `:utc_offset`, and
  `:std_offset` keys (a `t:DateTime.t/0` satisfies this shape).

* `locale_id` is a **resolved** locale identifier atom (e.g., `:en`),
  such as the `cldr_locale_id` of a validated
  `t:Localize.LanguageTag.t/0`. It is passed directly to
  `Localize.Locale.get/2` and is not validated or canonicalized
  by this function.

* `options` is a keyword list of options.

### Options

* `:format` is `:short` (e.g., `"EST"`) or `:long` (e.g.,
  `"Eastern Standard Time"`). The default is `:long`.

* `:type` is `:specific` (standard or daylight name chosen from
  the datetime's `:std_offset`), `:generic`, `:standard`, or
  `:daylight`. The default is `:specific`.

### Returns

* `{:ok, timezone_name}` with the localized non-location name, or
  `{:ok, gmt_offset_string}` when falling back to the GMT format.

* `{:error, exception}` if the locale's timezone data cannot be
  loaded.

### Examples

    iex> datetime = %{time_zone: "America/New_York", utc_offset: -18000, std_offset: 0}
    iex> Localize.DateTime.Timezone.non_location_format(datetime, :en, format: :long)
    {:ok, "Eastern Standard Time"}

    iex> datetime = %{time_zone: "America/New_York", utc_offset: -18000, std_offset: 0}
    iex> Localize.DateTime.Timezone.non_location_format(datetime, :en, format: :short)
    {:ok, "EST"}

# `territories_by_timezone`

```elixir
@spec territories_by_timezone() :: %{required(String.t()) =&gt; atom()}
```

Returns a mapping of IANA time zone names to their
known territory.

A time zone can only belong to one territory in CLDR.

### Returns

* A map where each key is an IANA timezone string and each
  value is a territory atom.

### Examples

    iex> territories = Localize.DateTime.Timezone.territories_by_timezone()
    iex> Map.get(territories, "Australia/Sydney")
    :AU

# `timezone_count_for_territory`

```elixir
@spec timezone_count_for_territory(atom()) ::
  {:ok, non_neg_integer()} | {:error, Exception.t()}
```

Returns the count of timezones for a given territory.

### Arguments

* `territory` is a territory atom like `:US` or `:AU`.

### Returns

* `{:ok, count}` where count is the number of timezones.

* `{:error, exception}` if the territory has no known timezones.

### Examples

    iex> {:ok, count} = Localize.DateTime.Timezone.timezone_count_for_territory(:AU)
    iex> count > 0
    true

# `timezones`

```elixir
@spec timezones() :: %{required(String.t()) =&gt; map()}
```

Returns a mapping of CLDR short zone codes to
IANA timezone names.

Each key is a BCP 47 short timezone identifier string and each
value is a map with `:aliases`, `:preferred`, and `:territory`
keys.

### Returns

* A map of `%{String.t() => map()}`.

### Examples

    iex> timezones = Localize.DateTime.Timezone.timezones()
    iex> Map.get(timezones, "ausyd")
    %{preferred: nil, aliases: ["Australia/Sydney", "Australia/ACT", "Australia/Canberra", "Australia/NSW"], territory: :AU}

# `timezones_by_territory`

```elixir
@spec timezones_by_territory() :: %{
  required(atom()) =&gt; [
    %{
      short_zone: String.t(),
      territory: atom(),
      aliases: [term(), ...],
      preferred: nil | String.t()
    },
    ...
  ]
}
```

Returns a mapping of territories to their known IANA
timezone names.

### Returns

* A map where each key is a territory atom and each value is a
  list of timezone maps including `:short_zone`, `:aliases`,
  `:preferred`, and `:territory` keys.

### Examples

    iex> {:ok, zones} = Localize.DateTime.Timezone.timezones_for_territory(:AU)
    iex> Enum.any?(zones, & &1.short_zone == "ausyd")
    true

# `timezones_for_territory`

```elixir
@spec timezones_for_territory(atom()) :: {:ok, [map()]} | {:error, Exception.t()}
```

Returns a list of timezone maps for a given territory.

### Arguments

* `territory` is a territory atom like `:US` or `:AU`.

### Returns

* `{:ok, list}` where list is timezone maps for the territory.

* `{:error, exception}` if the territory has no known timezones.

### Examples

    iex> {:ok, zones} = Localize.DateTime.Timezone.timezones_for_territory(:US)
    iex> is_list(zones)
    true

# `validate_short_zone`

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

Validates a CLDR short zone code and returns the canonical
IANA timezone name.

### Arguments

* `short_zone` is a CLDR short timezone code string.

### Returns

* `{:ok, iana_name}` where `iana_name` is the canonical IANA
  timezone name string.

* `{:error, exception}` if the short zone code is not valid.

### Examples

    iex> Localize.DateTime.Timezone.validate_short_zone("ausyd")
    {:ok, "Australia/Sydney"}

    iex> Localize.DateTime.Timezone.validate_short_zone("nope")
    {:error, %Localize.UnknownTimezoneError{timezone: "nope"}}

# `zone_for_metazone`

```elixir
@spec zone_for_metazone(atom(), atom()) :: String.t() | nil
```

Returns the IANA timezone that represents a CLDR metazone.

### Arguments

* `metazone` is a metazone atom as returned by `metazone_for/2`
  (e.g., `:america_pacific`).

* `territory` is a territory atom used to select a
  territory-specific representative zone (e.g., `:CA` selects
  `"America/Vancouver"` for `:america_pacific`). The default is
  `:"001"`, the metazone's golden zone.

### Returns

* The IANA timezone name for the territory, falling back to the
  metazone's golden zone when the territory has no specific
  mapping.

* `nil` when the metazone is unknown.

### Examples

    iex> Localize.DateTime.Timezone.zone_for_metazone(:america_pacific)
    "America/Los_Angeles"

    iex> Localize.DateTime.Timezone.zone_for_metazone(:america_pacific, :CA)
    "America/Vancouver"

    iex> Localize.DateTime.Timezone.zone_for_metazone(:no_such_metazone)
    nil

---

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