Current section

Files

Jump to
ex_cldr_dates_times lib cldr backend format.ex
Raw

lib/cldr/backend/format.ex

defmodule Cldr.DateTime.Format.Backend do
@moduledoc false
def define_date_time_format_module(config) do
backend = config.backend
config = Macro.escape(config)
module = inspect(__MODULE__)
quote location: :keep, bind_quoted: [config: config, backend: backend, module: module] do
defmodule DateTime.Format do
@moduledoc false
if Cldr.Config.include_module_docs?(config.generate_docs) do
@moduledoc """
Manages the Date, TIme and DateTime formats
defined by CLDR.
The functions in `Cldr.DateTime.Format` are
primarily concerned with encapsulating the
data from CLDR in functions that are used
during the formatting process.
"""
end
alias Cldr.Locale
alias Cldr.LanguageTag
alias Cldr.Config
alias Cldr.DateTime.Format
@standard_formats [:short, :medium, :long, :full]
@date_symbols [
"Y",
"y",
"G",
"M",
"L",
"D",
"d",
"U",
"u",
"Q",
"q",
"F",
"g",
"W",
"w",
"E",
"e",
"c"
]
@time_symbols [
"H",
"h",
"K",
"k",
"C",
"m",
"s",
"S",
"A",
"Z",
"z",
"V",
"v",
"X",
"x",
"O"
]
@doc "A struct from a format id as an atom to a format string"
@type formats :: map()
@doc "The CLDR calendar type as an atom"
@type calendar :: atom()
@doc """
Returns a list of calendars defined for a given locale.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
## Example
iex> #{inspect(__MODULE__)}.calendars_for(:en)
{:ok, [:buddhist, :chinese, :coptic, :dangi, :ethiopic, :ethiopic_amete_alem,
:generic, :gregorian, :hebrew, :indian, :islamic, :islamic_civil,
:islamic_rgsa, :islamic_tbla, :islamic_umalqura, :iso8601, :japanese, :persian, :roc]}
"""
@spec calendars_for(Locale.locale_reference()) ::
{:ok, [calendar, ...]} | {:error, {module(), String.t()}}
def calendars_for(locale \\ unquote(backend).get_locale())
def calendars_for(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
calendars_for(cldr_locale_name)
end
def calendars_for(locale_name) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
calendars_for(locale)
end
end
@doc """
Returns a map of the standard date formats for a given locale and calendar.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
* `calendar` is any calendar returned by `Cldr.DateTime.Format.calendars_for/1`
The default is `:gregorian`.
## Examples:
iex> #{inspect(__MODULE__)}.date_formats(:en)
{:ok, %Cldr.Date.Formats{
full: "EEEE, MMMM d, y",
long: "MMMM d, y",
medium: "MMM d, y",
short: "M/d/yy"
}}
iex> #{inspect(__MODULE__)}.date_formats(:en, :buddhist)
{:ok, %Cldr.Date.Formats{
full: "EEEE, MMMM d, y G",
long: "MMMM d, y G",
medium: "MMM d, y G",
short: "M/d/y GGGGG"
}}
"""
@spec date_formats(Locale.locale_reference(), calendar) ::
{:ok, map()} | {:error, {module(), String.t()}}
def date_formats(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)
def date_formats(%LanguageTag{cldr_locale_name: cldr_locale_name}, calendar) do
date_formats(cldr_locale_name, calendar)
end
def date_formats(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
date_formats(locale, calendar)
end
end
@doc """
Returns a map of the standard time formats for a given locale and calendar.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
* `calendar` is any calendar returned by `Cldr.DateTime.Format.calendars_for/1`
The default is `:gregorian`.
## Examples:
iex> #{inspect(__MODULE__)}.time_formats(:en)
{
:ok,
%Cldr.Time.Formats{
full: %{unicode: "h:mm:ss a zzzz", ascii: "h:mm:ss a zzzz"},
long: %{unicode: "h:mm:ss a z", ascii: "h:mm:ss a z"},
medium: %{unicode: "h:mm:ss a", ascii: "h:mm:ss a"},
short: %{unicode: "h:mm a", ascii: "h:mm a"}
}
}
iex> #{inspect(__MODULE__)}.time_formats(:en, :buddhist)
{
:ok,
%Cldr.Time.Formats{
full: %{unicode: "h:mm:ss a zzzz", ascii: "h:mm:ss a zzzz"},
long: %{unicode: "h:mm:ss a z", ascii: "h:mm:ss a z"},
medium: %{unicode: "h:mm:ss a", ascii: "h:mm:ss a"},
short: %{unicode: "h:mm a", ascii: "h:mm a"}
}
}
"""
@spec time_formats(Locale.locale_reference(), calendar) ::
{:ok, map()} | {:error, {module(), String.t()}}
def time_formats(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)
def time_formats(%LanguageTag{cldr_locale_name: cldr_locale_name}, calendar) do
time_formats(cldr_locale_name, calendar)
end
def time_formats(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
time_formats(locale, calendar)
end
end
@doc """
Returns a map of the standard datetime formats for a given locale and calendar.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
* `calendar` is any calendar returned by `Cldr.DateTime.Format.calendars_for/1`
The default is `:gregorian`.
## Examples:
iex> #{inspect(__MODULE__)}.date_time_formats(:en)
{:ok, %Cldr.DateTime.Formats{
full: "{1}, {0}",
long: "{1}, {0}",
medium: "{1}, {0}",
short: "{1}, {0}"
}}
iex> #{inspect(__MODULE__)}.date_time_formats(:en, :buddhist)
{:ok, %Cldr.DateTime.Formats{
full: "{1}, {0}",
long: "{1}, {0}",
medium: "{1}, {0}",
short: "{1}, {0}"
}}
"""
@spec date_time_formats(Locale.locale_reference(), calendar) ::
{:ok, map()} | {:error, {module(), String.t()}}
def date_time_formats(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)
def date_time_formats(%LanguageTag{cldr_locale_name: cldr_locale_name}, cldr_calendar) do
date_time_formats(cldr_locale_name, cldr_calendar)
end
def date_time_formats(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
date_time_formats(locale, calendar)
end
end
@doc """
Returns a map of the standard datetime "at" formats for a given
locale and calendar.
An "at" format is one where the datetime is formatted with the
date part separated from the time part by a localized version
of "at".
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
* `calendar` is any calendar returned by `Cldr.DateTime.Format.calendars_for/1`
The default is `:gregorian`,
## Examples:
iex> #{inspect(__MODULE__)}.date_time_at_formats(:en)
{:ok, %Cldr.DateTime.Formats{
full: "{1} 'at' {0}",
long: "{1} 'at' {0}",
medium: "{1}, {0}",
short: "{1}, {0}"}
}
iex> #{inspect(__MODULE__)}.date_time_at_formats(:en, :buddhist)
{:ok, %Cldr.DateTime.Formats{
full: "{1} 'at' {0}",
long: "{1} 'at' {0}",
medium: "{1}, {0}",
short: "{1}, {0}"}
}
"""
@spec date_time_at_formats(Locale.locale_reference(), calendar) ::
{:ok, map()} | {:error, {module(), String.t()}}
def date_time_at_formats(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)
def date_time_at_formats(%LanguageTag{cldr_locale_name: cldr_locale_name}, cldr_calendar) do
date_time_at_formats(cldr_locale_name, cldr_calendar)
end
def date_time_at_formats(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
date_time_at_formats(locale, calendar)
end
end
@doc """
Returns a map of the available datetime formats for a
given locale and calendar.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
* `calendar` is any calendar returned by `Cldr.DateTime.Format.calendars_for/1`
The default is `:gregorian`.
## Examples:
iex> #{inspect(__MODULE__)}.date_time_available_formats "en"
{:ok,
%{
yw: %{
other: "'week' w 'of' Y",
one: "'week' w 'of' Y",
pluralize: :week_of_year
},
GyMMMEd: "E, MMM d, y G",
Hms: "HH:mm:ss",
MMMMW: %{
other: "'week' W 'of' MMMM",
one: "'week' W 'of' MMMM",
pluralize: :week_of_month
},
E: "ccc",
MMMd: "MMM d",
yMEd: "E, M/d/y",
yQQQ: "QQQ y",
Ehm: %{unicode: "E h:mm a", ascii: "E h:mm a"},
M: "L",
hm: %{unicode: "h:mm a", ascii: "h:mm a"},
yM: "M/y",
GyMMMd: "MMM d, y G",
GyMd: "M/d/y G",
Gy: "y G",
Hm: "HH:mm",
EBhms: "E h:mm:ss B",
d: "d",
hms: %{unicode: "h:mm:ss a", ascii: "h:mm:ss a"},
Ed: "d E",
Ehms: %{unicode: "E h:mm:ss a", ascii: "E h:mm:ss a"},
EHms: "E HH:mm:ss",
Bh: "h B",
h: %{unicode: "h a", ascii: "h a"},
Bhms: "h:mm:ss B",
Hmv: "HH:mm v",
hmv: %{unicode: "h:mm a v", ascii: "h:mm a v"},
yMd: "M/d/y",
ms: "mm:ss",
MMM: "LLL",
y: "y",
Bhm: "h:mm B",
yMMM: "MMM y",
yQQQQ: "QQQQ y",
yMMMEd: "E, MMM d, y",
yMMMM: "MMMM y",
EBhm: "E h:mm B",
Hmsv: "HH:mm:ss v",
yMMMd: "MMM d, y",
MEd: "E, M/d",
EHm: "E HH:mm",
GyMMM: "MMM y G",
hmsv: %{unicode: "h:mm:ss a v", ascii: "h:mm:ss a v"},
H: "HH",
Md: "M/d",
MMMEd: "E, MMM d",
MMMMd: "MMMM d"
}}
"""
@spec date_time_available_formats(Locale.locale_reference(), calendar) ::
{:ok, formats} | {:error, {module, String.t()}}
def date_time_available_formats(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)
def date_time_available_formats(
%LanguageTag{cldr_locale_name: cldr_locale_name},
calendar
) do
date_time_available_formats(cldr_locale_name, calendar)
end
def date_time_available_formats(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
date_time_available_formats(locale, calendar)
end
end
@doc """
Returns a map of the available date formats for a
given locale and calendar.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
* `calendar` is any calendar returned by `Cldr.DateTime.Format.calendars_for/1`
The default is `:gregorian`.
## Examples:
iex> #{inspect(__MODULE__)}.date_available_formats "en"
"""
@spec date_available_formats(Locale.locale_reference(), calendar) ::
{:ok, formats} | {:error, {module, String.t()}}
def date_available_formats(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)
def date_available_formats(
%LanguageTag{cldr_locale_name: cldr_locale_name},
calendar
) do
date_available_formats(cldr_locale_name, calendar)
end
def date_available_formats(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
date_available_formats(locale, calendar)
end
end
@doc """
Returns a map of the available time formats for a
given locale and calendar.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
* `calendar` is any calendar returned by `Cldr.DateTime.Format.calendars_for/1`
The default is `:gregorian`.
## Examples:
iex> #{inspect(__MODULE__)}.time_available_formats :en
"""
@spec time_available_formats(Locale.locale_reference(), calendar) ::
{:ok, formats} | {:error, {module, String.t()}}
def time_available_formats(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)
def time_available_formats(
%LanguageTag{cldr_locale_name: cldr_locale_name},
calendar
) do
time_available_formats(cldr_locale_name, calendar)
end
def time_available_formats(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
time_available_formats(locale, calendar)
end
end
@doc false
def date_time_available_format_tokens(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)
def date_time_available_format_tokens(
%LanguageTag{cldr_locale_name: cldr_locale_name},
calendar
) do
date_time_available_format_tokens(cldr_locale_name, calendar)
end
def date_time_available_format_tokens(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
date_time_available_format_tokens(locale, calendar)
end
end
@doc """
Returns a map of the interval formats for a
given locale and calendar.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
* `calendar` is any calendar returned by `Cldr.DateTime.Format.calendars_for/1`
The default is `:gregorian`.
## Examples:
iex> #{inspect(__MODULE__)}.date_time_interval_formats(:en, :gregorian)
{:ok,
%{
h: %{a: ["h a – ", "h a"], h: ["h – ", "h a"]},
d: %{d: ["d – ", "d"]},
y: %{y: ["y – ", "y"]},
M: %{M: ["M – ", "M"]},
Bh: %{h: ["h – ", "h B"], B: ["h B – ", "h B"]},
Bhm: %{
m: ["h:mm – ", "h:mm B"],
h: ["h:mm – ", "h:mm B"],
B: ["h:mm B – ", "h:mm B"]
},
Gy: %{y: ["y – ", "y G"], G: ["y G – ", "y G"]},
GyMMM: %{
y: ["MMM y – ", "MMM y G"],
M: ["MMM – ", "MMM y G"],
G: ["MMM y G – ", "MMM y G"]
},
GyMMMEd: %{
d: ["E, MMM d – ", "E, MMM d, y G"],
y: ["E, MMM d, y – ", "E, MMM d, y G"],
M: ["E, MMM d – ", "E, MMM d, y G"],
G: ["E, MMM d, y G – ", "E, MMM d, y G"]
},
GyMMMd: %{
d: ["MMM d – ", "d, y G"],
y: ["MMM d, y – ", "MMM d, y G"],
M: ["MMM d – ", "MMM d, y G"],
G: ["MMM d, y G – ", "MMM d, y G"]
},
GyMd: %{
d: ["M/d/y – ", "M/d/y G"],
y: ["M/d/y – ", "M/d/y G"],
M: ["M/d/y – ", "M/d/y G"],
G: ["M/d/y G – ", "M/d/y G"]
},
H: %{H: ["HH – ", "HH"]},
Hm: %{m: ["HH:mm – ", "HH:mm"], H: ["HH:mm – ", "HH:mm"]},
Hmv: %{m: ["HH:mm – ", "HH:mm v"], H: ["HH:mm – ", "HH:mm v"]},
MEd: %{d: ["E, M/d – ", "E, M/d"], M: ["E, M/d – ", "E, M/d"]},
MMM: %{M: ["MMM – ", "MMM"]},
MMMEd: %{
d: ["E, MMM d – ", "E, MMM d"],
M: ["E, MMM d – ", "E, MMM d"]
},
MMMd: %{d: ["MMM d – ", "d"], M: ["MMM d – ", "MMM d"]},
Md: %{d: ["M/d – ", "M/d"], M: ["M/d – ", "M/d"]},
hm: %{
m: ["h:mm – ", "h:mm a"],
a: ["h:mm a – ", "h:mm a"],
h: ["h:mm – ", "h:mm a"]
},
hmv: %{
m: ["h:mm – ", "h:mm a v"],
a: ["h:mm a – ", "h:mm a v"],
h: ["h:mm – ", "h:mm a v"]
},
yM: %{y: ["M/y – ", "M/y"], M: ["M/y – ", "M/y"]},
yMEd: %{
d: ["E, M/d/y – ", "E, M/d/y"],
y: ["E, M/d/y – ", "E, M/d/y"],
M: ["E, M/d/y – ", "E, M/d/y"]
},
yMMM: %{y: ["MMM y – ", "MMM y"], M: ["MMM – ", "MMM y"]},
yMMMEd: %{
d: ["E, MMM d – ", "E, MMM d, y"],
y: ["E, MMM d, y – ", "E, MMM d, y"],
M: ["E, MMM d – ", "E, MMM d, y"]
},
yMMMM: %{y: ["MMMM y – ", "MMMM y"], M: ["MMMM – ", "MMMM y"]},
yMMMd: %{
d: ["MMM d – ", "d, y"],
y: ["MMM d, y – ", "MMM d, y"],
M: ["MMM d – ", "MMM d, y"]
},
yMd: %{
d: ["M/d/y – ", "M/d/y"],
y: ["M/d/y – ", "M/d/y"],
M: ["M/d/y – ", "M/d/y"]
},
GyM: %{
y: ["M/y – ", "M/y G"],
M: ["M/y – ", "M/y G"],
G: ["M/y G – ", "M/y G"]
},
GyMEd: %{
d: ["E, M/d/y – ", "E, M/d/y G"],
y: ["E, M/d/y – ", "E, M/d/y G"],
M: ["E, M/d/y – ", "E, M/d/y G"],
G: ["E, M/d/y G – ", "E, M/d/y G"]
},
Hv: %{H: ["HH – ", "HH v"]},
hv: %{a: ["h a – ", "h a v"], h: ["h – ", "h a v"]}
}}
"""
@spec date_time_interval_formats(Locale.locale_reference(), calendar()) ::
{:ok, formats} | {:error, {module, String.t()}}
def date_time_interval_formats(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)
def date_time_interval_formats(
%LanguageTag{cldr_locale_name: cldr_locale_name},
calendar
) do
date_time_interval_formats(cldr_locale_name, calendar)
end
def date_time_interval_formats(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
date_time_interval_formats(locale, calendar)
end
end
@doc """
Returns a list of the date_time format IDs that are
available in all known locales.
The format IDs returned by `common_date_time_format_names/0`
are guaranteed to be available in all known locales,
## Example:
iex> #{inspect(__MODULE__)}.common_date_time_format_names()
[:Bh, :Bhm, :Bhms, :E, :EBhm, :EBhms, :EHm, :EHms, :Ed, :Ehm, :Ehms, :Gy,
:GyMMM, :GyMMMEd, :GyMMMd, :GyMd, :H, :Hm, :Hms, :Hmsv, :Hmv, :M, :MEd, :MMM,
:MMMEd, :MMMMW, :MMMMd, :MMMd, :Md, :d, :h, :hm, :hms, :hmsv, :hmv, :ms, :y,
:yM, :yMEd, :yMMM, :yMMMEd, :yMMMM, :yMMMd, :yMd, :yQQQ, :yQQQQ, :yw]
"""
@spec common_date_time_format_names() :: [Format.format_id()]
def common_date_time_format_names do
Cldr.DateTime.Format.common_date_time_format_names(unquote(backend))
end
@doc """
Returns the fallback format for a given
locale and calendar type
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
* `calendar` is any calendar returned by `Cldr.DateTime.Format.calendars_for/1`
The default is `:gregorian`.
## Examples:
iex> #{inspect(__MODULE__)}.date_time_interval_fallback(:en, :gregorian)
[0, " – ", 1]
"""
@spec date_time_interval_fallback(Locale.locale_reference(), calendar()) ::
list() | {:error, {module(), String.t()}}
def date_time_interval_fallback(
locale \\ unquote(backend).get_locale(),
calendar \\ Cldr.Calendar.default_cldr_calendar()
)
def date_time_interval_fallback(
%LanguageTag{cldr_locale_name: cldr_locale_name},
calendar
) do
date_time_interval_fallback(cldr_locale_name, calendar)
end
def date_time_interval_fallback(locale_name, calendar) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
date_time_interval_fallback(locale, calendar)
end
end
@doc """
Returns the positive and negative hour format
for a timezone offset for a given locale.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
## Example
iex> #{inspect(__MODULE__)}.hour_format("en")
{:ok, {"+HH:mm", "-HH:mm"}}
"""
@spec hour_format(Locale.locale_reference()) ::
{:ok, {String.t(), String.t()}} | {:error, {module, String.t()}}
def hour_format(locale \\ unquote(backend).get_locale())
def hour_format(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
hour_format(cldr_locale_name)
end
def hour_format(locale_name) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
hour_format(locale)
end
end
@doc """
Returns the GMT offset format list for a
for a timezone offset for a given locale.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
## Example
iex> #{inspect(__MODULE__)}.gmt_format(:en)
{:ok, ["GMT", 0]}
"""
@spec gmt_format(Locale.locale_reference()) ::
{:ok, [non_neg_integer | String.t(), ...]} | {:error, {module, String.t()}}
def gmt_format(locale \\ unquote(backend).get_locale())
def gmt_format(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
gmt_format(cldr_locale_name)
end
def gmt_format(locale_name) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
gmt_format(locale)
end
end
@doc """
Returns the GMT format string for a
for a timezone with an offset of zero for
a given locale.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
## Example
iex> #{inspect(__MODULE__)}.gmt_zero_format(:en)
{:ok, "GMT"}
iex> #{inspect(__MODULE__)}.gmt_zero_format(:fr)
{:ok, "UTC"}
"""
@spec gmt_zero_format(Locale.locale_reference()) ::
{:ok, String.t()} | {:error, {module(), String.t()}}
def gmt_zero_format(locale \\ unquote(backend).get_locale())
def gmt_zero_format(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
gmt_zero_format(cldr_locale_name)
end
def gmt_zero_format(locale_name) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
gmt_zero_format(locale)
end
end
@doc """
Returns the time zone region format map for
a given locale.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
## Example
iex> #{inspect(__MODULE__)}.zone_region_format(:en)
{:ok,
%{
standard: [0, " Standard Time"],
generic: [0, " Time"],
daylight: [0, " Daylight Time"]
}
}
"""
@spec zone_region_format(Locale.locale_reference()) ::
{:ok, map()} | {:error, {module(), String.t()}}
def zone_region_format(locale \\ unquote(backend).get_locale())
def zone_region_format(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
zone_region_format(cldr_locale_name)
end
def zone_region_format(locale_name) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
zone_region_format(locale)
end
end
@doc """
Returns the time zone fallback format map for
a given locale.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
## Example
iex> #{inspect(__MODULE__)}.zone_fallback_format(:en)
{:ok, [1, " (", 0, ")"]}
"""
@spec zone_fallback_format(Locale.locale_reference()) ::
{:ok, list()} | {:error, {module(), String.t()}}
def zone_fallback_format(locale \\ unquote(backend).get_locale())
def zone_fallback_format(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
zone_fallback_format(cldr_locale_name)
end
def zone_fallback_format(locale_name) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
zone_fallback_format(locale)
end
end
@doc """
Returns the localized territory names.
## Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
## Example
iex> {:ok, territories} = #{inspect(__MODULE__)}.territories(:en)
iex> Map.get(territories, :AU)
%{standard: "Australia"}
iex> {:ok, territories} = #{inspect(__MODULE__)}.territories(:en)
iex> Map.get(territories, :NZ)
%{standard: "New Zealand", variant: "Aotearoa New Zealand"}
iex> {:ok, territories} = #{inspect(__MODULE__)}.territories(:en)
iex> Map.get(territories, :US)
%{short: "US", standard: "United States"}
"""
@spec territories(Locale.locale_reference()) ::
{:ok, map()} | {:error, {module(), String.t()}}
def territories(locale \\ unquote(backend).get_locale())
def territories(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
territories(cldr_locale_name)
end
def territories(locale_name) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
territories(locale)
end
end
@doc """
Returns the timezone data for a locale.
### Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
### Returns
* a map of localized timezone display data.
"""
@doc since: "2.33.0"
@spec time_zones(Locale.locale_reference()) ::
{:ok, map()} | {:error, {module(), String.t()}}
def time_zones(locale \\ unquote(backend).get_locale())
def time_zones(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
time_zones(cldr_locale_name)
end
def time_zones(locale_name) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
time_zones(locale)
end
end
@doc """
Returns the metazone data for a locale.
### Arguments
* `locale` is any locale returned by `Cldr.known_locale_names/0`
or a `t:Cldr.LanguageTag.t/0`. The default is `Cldr.get_locale/0`.
### Returns
* a map of localized metazone display data.
"""
@doc since: "2.33.0"
@spec meta_zones(Locale.locale_reference()) ::
{:ok, map()} | {:error, {module(), String.t()}}
def meta_zones(locale \\ unquote(backend).get_locale())
def meta_zones(%LanguageTag{cldr_locale_name: cldr_locale_name}) do
meta_zones(cldr_locale_name)
end
def meta_zones(locale_name) when is_binary(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
meta_zones(locale)
end
end
for locale <- Cldr.Locale.Loader.known_locale_names(config) do
locale_data = Cldr.Locale.Loader.get_locale(locale, config)
calendars = Cldr.Config.calendars_for_locale(locale, config)
time_zones =
get_in(locale_data, [:dates, :time_zone_names, :zone])
|> Macro.escape()
meta_zones =
get_in(locale_data, [:dates, :time_zone_names, :metazone])
|> Macro.escape()
zone_fallback_format =
get_in(locale_data, [:dates, :time_zone_names, :fallback_format])
|> Macro.escape()
zone_region_format =
get_in(locale_data, [:dates, :time_zone_names, :region_format])
|> Macro.escape()
territories =
get_in(locale_data, [:territories])
|> Macro.escape()
def calendars_for(unquote(locale)), do: {:ok, unquote(calendars)}
def gmt_format(unquote(locale)),
do: {:ok, unquote(get_in(locale_data, [:dates, :time_zone_names, :gmt_format]))}
def gmt_zero_format(unquote(locale)),
do: {:ok, unquote(get_in(locale_data, [:dates, :time_zone_names, :gmt_zero_format]))}
def time_zones(unquote(locale)),
do: {:ok, unquote(time_zones)}
def meta_zones(unquote(locale)),
do: {:ok, unquote(meta_zones)}
def zone_fallback_format(unquote(locale)),
do: {:ok, unquote(zone_fallback_format)}
def zone_region_format(unquote(locale)),
do: {:ok, unquote(zone_region_format)}
def territories(unquote(locale)),
do: {:ok, unquote(territories)}
hour_formats =
locale_data
|> get_in([:dates, :time_zone_names, :hour_format])
|> String.split(";")
|> Elixir.List.to_tuple()
def hour_format(unquote(locale)), do: {:ok, unquote(hour_formats)}
for calendar <- calendars do
calendar_data =
locale_data
|> Map.get(:dates)
|> get_in([:calendars, calendar])
date_formats = struct(Cldr.Date.Formats, Map.get(calendar_data, :date_formats))
def date_formats(unquote(locale), unquote(calendar)) do
{:ok, unquote(Macro.escape(date_formats))}
end
time_formats = struct(Cldr.Time.Formats, Map.get(calendar_data, :time_formats))
def time_formats(unquote(locale), unquote(calendar)) do
{:ok, unquote(Macro.escape(time_formats))}
end
date_time_formats =
struct(
Cldr.DateTime.Formats,
Map.get(calendar_data, :date_time_formats)
|> Map.take(@standard_formats)
)
def date_time_formats(unquote(locale), unquote(calendar)) do
{:ok, unquote(Macro.escape(date_time_formats))}
end
date_time_at_formats =
struct(
Cldr.DateTime.Formats,
Map.get(calendar_data, :date_time_formats_at_time)
|> Map.get(:standard)
|> Map.take(@standard_formats)
)
def date_time_at_formats(unquote(locale), unquote(calendar)) do
{:ok, unquote(Macro.escape(date_time_at_formats))}
end
# For available formats we need to check for formats that have
# pluralization rules. For those rules we capture the field that
# is pluralizad at runtime - its the last token in the tokenized
# name of the format.
available_formats =
calendar_data
|> get_in([:date_time_formats, :available_formats])
|> Enum.map(fn
{name, %{other: _other} = plurals} ->
{:ok, tokens, _} = Cldr.DateTime.Format.Compiler.tokenize(to_string(name))
[{pluralize, _, _} | _rest] = Enum.reverse(tokens)
{name, Map.put(plurals, :pluralize, pluralize)}
other ->
other
end)
|> Map.new()
def date_time_available_formats(unquote(locale), unquote(calendar)) do
{:ok, unquote(Macro.escape(available_formats))}
end
date_available_formats =
Enum.filter(available_formats, fn {format_id, _} ->
remaining =
format_id
|> to_string()
|> String.replace(@date_symbols, "")
remaining == ""
end)
|> Map.new()
def date_available_formats(unquote(locale), unquote(calendar)) do
{:ok, unquote(Macro.escape(date_available_formats))}
end
time_available_formats =
Enum.filter(available_formats, fn {format_id, _} ->
remaining =
format_id
|> to_string()
|> String.replace(@time_symbols, "")
remaining == ""
end)
|> Map.new()
def time_available_formats(unquote(locale), unquote(calendar)) do
{:ok, unquote(Macro.escape(time_available_formats))}
end
available_format_tokens =
Enum.map(available_formats, fn {format_id, format} ->
{:ok, tokens} = Cldr.DateTime.Format.Compiler.tokenize_skeleton(format_id)
{format_id, tokens}
end)
|> Map.new()
def date_time_available_format_tokens(unquote(locale), unquote(calendar)) do
unquote(Macro.escape(available_format_tokens))
end
interval_formats =
get_in(calendar_data, [:date_time_formats, :interval_formats])
interval_format_fallback =
get_in(
calendar_data,
[:date_time_formats, :interval_formats, :interval_format_fallback]
)
interval_formats =
interval_formats
|> Map.delete(:interval_format_fallback)
|> Enum.map(fn {k, v} ->
split_formats =
Enum.map(v, fn {k2, v2} ->
interval_formats = Cldr.DateTime.Format.split_interval!(v2)
{k2, interval_formats}
end)
|> Map.new()
{k, split_formats}
end)
|> Map.new()
def date_time_interval_formats(unquote(locale), unquote(calendar)) do
{:ok, unquote(Macro.escape(interval_formats))}
end
def date_time_interval_fallback(unquote(locale), unquote(calendar)) do
unquote(interval_format_fallback)
end
end
def date_formats(unquote(locale), calendar),
do: {:error, Cldr.Calendar.calendar_error(calendar)}
def time_formats(unquote(locale), calendar),
do: {:error, Cldr.Calendar.calendar_error(calendar)}
def date_time_formats(unquote(locale), calendar),
do: {:error, Cldr.Calendar.calendar_error(calendar)}
def date_time_at_formats(unquote(locale), calendar),
do: {:error, Cldr.Calendar.calendar_error(calendar)}
def date_time_available_formats(unquote(locale), calendar),
do: {:error, Cldr.Calendar.calendar_error(calendar)}
def date_time_interval_formats(unquote(locale), calendar),
do: {:error, Cldr.Calendar.calendar_error(calendar)}
def date_time_interval_fallback(unquote(locale), calendar),
do: {:error, Cldr.Calendar.calendar_error(calendar)}
end
def calendars_for(locale), do: {:error, Locale.locale_error(locale)}
def gmt_format(locale), do: {:error, Locale.locale_error(locale)}
def gmt_zero_format(locale), do: {:error, Locale.locale_error(locale)}
def time_zones(locale), do: {:error, Locale.locale_error(locale)}
def meta_zones(locale), do: {:error, Locale.locale_error(locale)}
def zone_region_format(locale), do: {:error, Locale.locale_error(locale)}
def zone_fallback_format(locale), do: {:error, Locale.locale_error(locale)}
def territories(locale), do: {:error, Locale.locale_error(locale)}
def hour_format(locale), do: {:error, Locale.locale_error(locale)}
def date_formats(locale, _calendar), do: {:error, Locale.locale_error(locale)}
def time_formats(locale, _calendar), do: {:error, Locale.locale_error(locale)}
def date_time_formats(locale, _calendar), do: {:error, Locale.locale_error(locale)}
def date_time_at_formats(locale, _calendar), do: {:error, Locale.locale_error(locale)}
def date_time_available_formats(locale, _calendar),
do: {:error, Locale.locale_error(locale)}
def date_time_interval_formats(locale, _calendar),
do: {:error, Locale.locale_error(locale)}
def date_time_interval_fallback(locale, _calendar),
do: {:error, Locale.locale_error(locale)}
@doc """
Returns the time period for a given time of day.
## Arguments
* `time` is any `Time.t` or a map with at least `:hour`,
`:minute` and `:second` keys
* `language` is a binary representation of a valid and
configured language in `Cldr`
The time period is a locale-specific key that is used
to localise a time into a textual representation of "am",
"pm", "noon", "midnight", "evening", "morning" and so on
as defined in the CLDR day period rules.
## Examples
iex> #{inspect(__MODULE__)}.day_period_for(~T[06:05:54.515228], :en)
:morning1
iex> #{inspect(__MODULE__)}.day_period_for(~T[13:05:54.515228], :en)
:afternoon1
iex> #{inspect(__MODULE__)}.day_period_for(~T[21:05:54.515228], :en)
:night1
iex> #{inspect(__MODULE__)}.day_period_for(~T[21:05:54.515228], :fr)
:evening1
"""
@spec day_period_for(
Elixir.Calendar.time(),
LanguageTag.t() | String.t() | Locale.locale_name()
) ::
atom | {:error, {module, String.t()}}
def day_period_for(time, language)
def day_period_for(time, %LanguageTag{language: language}) do
day_period_for(time, language)
end
@doc """
Returns a boolean indicating is a given language defines the
notion of "noon" and "midnight"
## Arguments
* `language` is a binary representation of a valid and
configured language in `Cldr`
## Examples
iex> #{inspect(__MODULE__)}.language_has_noon_and_midnight? :fr
true
iex> #{inspect(__MODULE__)}.language_has_noon_and_midnight? :en
true
iex> #{inspect(__MODULE__)}.language_has_noon_and_midnight? :af
false
"""
@spec language_has_noon_and_midnight?(LanguageTag.t() | String.t() | Locale.locale_name()) ::
boolean | {:error, {module, String.t()}}
def language_has_noon_and_midnight?(locale)
def language_has_noon_and_midnight?(%LanguageTag{language: language}) do
language_has_noon_and_midnight?(language)
end
# Insert generated functions that will identify which time period key
# is appropriate for a given time value. Note that we sort the time
# periods such that the "at" periods come before the "from"/"before"
# periods so that the functions are defined in the right order.
for {language, periods} <- Cldr.Config.day_period_info() do
for {period, times} <- Enum.sort(periods, fn {_k, v}, _p2 -> !!Map.get(v, "at") end) do
case times do
%{"at" => [h, m]} ->
def day_period_for(%{hour: unquote(h), minute: unquote(m)}, unquote(language)) do
unquote(String.to_atom(period))
end
# For when the time range wraps around midnight
%{"from" => [h1, 0], "before" => [h2, 0]} when h2 < h1 ->
def day_period_for(%{hour: hour}, unquote(language))
when rem(hour, 24) >= unquote(h1) or rem(hour, 24) < unquote(h2) do
unquote(String.to_atom(period))
end
# For when the time range does not wrap around midnight
%{"from" => [h1, 0], "before" => [h2, 0]} ->
def day_period_for(%{hour: hour}, unquote(language))
when rem(hour, 24) >= unquote(h1) and rem(hour, 24) < unquote(h2) do
unquote(String.to_atom(period))
end
end
end
# We also need a way to find out of a language supports the
# concept of "noon" and "midnight"
if Map.get(periods, "noon") && Map.get(periods, "midnight") do
def language_has_noon_and_midnight?(unquote(language)), do: true
end
end
def language_has_noon_and_midnight?(locale_name) when is_atom(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
language_has_noon_and_midnight?(locale.language)
end
end
def day_period_for(time, locale_name) when is_atom(locale_name) do
with {:ok, locale} <- unquote(backend).validate_locale(locale_name) do
day_period_for(time, locale.language)
end
end
def day_period_for(time, locale) do
{:error, Locale.locale_error(locale)}
end
def language_has_noon_and_midnight?(_), do: false
end
end
end
end