Localize.DateTime.Timezone (Localize v0.45.0)

Copy Markdown View Source

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.

Summary

Functions

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

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

Returns the localized GMT offset format.

Returns the ISO 8601 timezone offset format.

Returns the CLDR metazone for an IANA timezone name.

Returns the specific or generic non-location timezone name.

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

Returns the count of timezones for a given territory.

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

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

Returns a list of timezone maps for a given territory.

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

Returns the IANA timezone that represents a CLDR metazone.

Functions

fetch_short_zone(short_zone)

@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(short_zone, default \\ nil)

@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(datetime, locale_id, options \\ [])

@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 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 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(datetime, options \\ [])

@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 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(time_zone, datetime \\ nil)

@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(datetime, locale_id, options \\ [])

@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 metazone name for the datetime's timezone in the locale's timezone data (e.g., "Eastern Standard Time"). When the timezone has no metazone mapping, or the locale carries no name for it, falls back to gmt_format/3.

Arguments

  • datetime is a map with :time_zone, :utc_offset, and :std_offset keys (a 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 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()

@spec territories_by_timezone() :: %{required(String.t()) => 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(territory)

@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()

@spec timezones() :: %{required(String.t()) => 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()

@spec timezones_by_territory() :: %{
  required(atom()) => [
    %{
      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(territory)

@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(short_zone)

@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(metazone, territory \\ :"001")

@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