Localize.Calendar (Localize v1.4.0)

Copy Markdown View Source

Calendar localization functions for retrieving locale-specific names for eras, months, days, quarters, and day periods.

Also provides territory-based week preferences (first day of week, weekend days) and functions to produce localized date part strings from Date, DateTime, and NaiveDateTime structs.

Display names

The display_name/3 function provides a unified API for localized calendar-related names, modeled on the JavaScript Intl.DisplayNames API:

TypeValueExample result
:calendar:gregorian"Gregorian Calendar"
:era1"Anno Domini"
:month1"January"
:day_of_week1 (ISO Monday)"Monday"
:quarter1"1st quarter"
:day_period:am"AM"
:date_time_field:year"year"

All types support :locale and :style options. The :month, :day_of_week, :quarter, and :day_period types also support a :context option (:format or :stand_alone).

:style is the display width — :wide (the default), :abbreviated, :narrow, or :short. Widths vary by type: only the day types carry :short, and a width the type does not have returns an error naming the widths it does.

Naming a date's parts

localize/3 is the same lookup addressed by a date rather than by an explicit value: localize(~D[2019-06-01], :month) and display_name(:month, 6) both return {:ok, "June"}. It derives the part's value from the date and delegates, so the two take the same options and always agree. Use it when you have a date, and display_name/3 when you have the value itself.

Data access

Lower-level data access functions (eras/2, months/2, days/2, quarters/2, day_periods/2) return full data maps for use in formatting pipelines.

Summary

Functions

Returns the acceptable CLDR calendar types.

Returns the module registered to answer for an application's calendars.

Returns the cyclic year names for a locale and calendar type.

Returns the day period names for a locale and calendar type.

Returns the day names for a locale and calendar type.

Returns a localized display name for a calendar-related item.

Returns the era names for a locale and calendar type.

Returns the first day of the week for a locale.

Returns the first day of the week for a territory.

Returns the list of known CLDR calendar types.

Returns a localized string for a part of a date or time.

Returns the minimum days in the first week of the year for a locale.

Returns the minimum days in the first week of the year for a territory.

Returns the month pattern data for a locale and calendar type.

Returns the month names for a locale and calendar type.

Returns the quarter names for a locale and calendar type.

Registers the module that answers for the calendars an application supplies.

Returns a keyword list of options for use with Calendar.strftime/3.

Returns the weekday numbers for a territory as a list of ISO day-of-week numbers.

Returns the weekend days for a territory as a list of ISO day-of-week numbers.

Types

context()

@type context() :: :format | :stand_alone

format()

@type format() :: :wide | :abbreviated | :narrow

part()

@type part() :: :era | :quarter | :month | :day_of_week | :days_of_week | :day_period

Functions

acceptable_calendars()

@spec acceptable_calendars() :: [atom(), ...]

Returns the acceptable CLDR calendar types.

Returns

  • A list of atoms.

Examples

iex> Localize.Calendar.acceptable_calendars()
[:gregorian, :buddhist, :chinese, :coptic, :dangi, :ethiopic, :ethiopic_amete_alem, :hebrew, :indian, :islamic, :islamic_civil, :islamic_rgsa, :islamic_tbla, :islamic_umalqura, :japanese, :persian, :roc]

calendar_provider()

@spec calendar_provider() :: module() | nil

Returns the module registered to answer for an application's calendars.

Returns

  • The provider module, or nil where none is registered.

Examples

iex> is_nil(Localize.Calendar.calendar_provider()) or
...>   is_atom(Localize.Calendar.calendar_provider())
true

cyclic_years(locale, calendar_type \\ :gregorian)

@spec cyclic_years(Localize.locale(), atom()) ::
  {:ok, map()} | {:error, Exception.t()}

Returns the cyclic year names for a locale and calendar type.

Cyclic year names are used by some calendar systems (such as Chinese and Dangi) that follow a 60-year cycle of named years.

Arguments

  • locale is a locale identifier atom, string, or Localize.LanguageTag.t/0.

  • calendar_type is a CLDR calendar type atom. The default is :gregorian.

Returns

  • {:ok, cyclic_year_data} where cyclic_year_data is a map of cyclic name sets.

  • {:error, exception} if the locale or calendar is not found.

Examples

iex> {:ok, cyclic} = Localize.Calendar.cyclic_years(:en, :chinese)
iex> Map.keys(cyclic) |> Enum.sort()
[:day_parts, :days, :months, :solar_terms, :years, :zodiacs]

iex> {:ok, cyclic} = Localize.Calendar.cyclic_years(:en, :chinese)
iex> get_in(cyclic, [:zodiacs, :format, :abbreviated, 1])
"Rat"

day_periods(locale, calendar_type \\ :gregorian)

@spec day_periods(Localize.locale(), atom()) :: {:ok, map()} | {:error, Exception.t()}

Returns the day period names for a locale and calendar type.

Day periods include AM/PM indicators and may include additional periods like noon, midnight, morning, afternoon, evening, and night.

Arguments

  • locale is a locale identifier atom, string, or Localize.LanguageTag.t/0.

  • calendar_type is a CLDR calendar type atom. The default is :gregorian.

Returns

  • {:ok, day_period_data} where day_period_data is a map keyed by context, format, period, and variant.

  • {:error, exception} if the locale or calendar is not found.

Examples

iex> {:ok, periods} = Localize.Calendar.day_periods(:en)
iex> get_in(periods, [:format, :abbreviated, :am, :default])
"AM"

days(locale, calendar_type \\ :gregorian)

@spec days(Localize.locale(), atom()) :: {:ok, map()} | {:error, Exception.t()}

Returns the day names for a locale and calendar type.

Arguments

  • locale is a locale identifier atom, string, or Localize.LanguageTag.t/0.

  • calendar_type is a CLDR calendar type atom. The default is :gregorian.

Returns

  • {:ok, day_data} where day_data is a map keyed by context (:format, :stand_alone), then format, then ISO day number (1 = Monday through 7 = Sunday).

  • {:error, exception} if the locale or calendar is not found.

Examples

iex> {:ok, days} = Localize.Calendar.days(:en)
iex> get_in(days, [:format, :wide, 6])
"Saturday"

display_name(type, value, options \\ [])

@spec display_name(atom(), term(), Keyword.t()) ::
  {:ok, String.t()} | {:error, Exception.t()}

Returns a localized display name for a calendar-related item.

This is a unified API for retrieving localized names for calendar systems, date-time fields, eras, months, days, quarters, and day periods — modeled on the JavaScript Intl.DisplayNames API.

Summary

TypeValueExample result
:calendar:gregorian"Gregorian Calendar"
:era1"Anno Domini"
:month1"January"
:day_of_week1 (ISO Monday)"Monday"
:quarter1"1st quarter"
:day_period:am"AM"
:date_time_field:year"year"

Arguments

  • type is the type of calendar item. One of:

    • :calendar — a calendar system name, in CLDR's form (:gregorian) or its BCP 47 form (:gregory).

    • :era — an era name by index (e.g., 1 for AD).

    • :quarter — a quarter name by number (1–4).

    • :month — a month name by number (1–12).

    • :day_of_week — a day-of-week name by ISO day number (1–7, Monday–Sunday).

    • :day_period — a day period name (e.g., :am, :pm, :noon, :midnight).

    • :date_time_field — a date-time field label (e.g., :year, :month, :day, :hour, :minute, :second).

  • value is the value to look up. The type depends on the type argument (see above).

  • options is a keyword list of options.

Options

  • :locale is a locale identifier. The default is Localize.get_locale().

  • :style is the display width. One of :wide (default), :abbreviated, :narrow, or :short. Not all styles are available for all types.

  • :context is :format (default) or :stand_alone. Applies to :month, :day_of_week, :quarter, and :day_period.

  • :day_period — if set to :variant, uses variant day period names ("am"/"pm" instead of "AM"/"PM" in English). Applies to the :day_period type.

  • :calendar is the calendar system atom. The default is :gregorian.

  • :prefer applies to the :calendar type. It is :standard (the default) for the full name, "Gregorian Calendar", or :menu for the short name CLDR gives for a menu of calendars, "Gregorian".

Returns

  • {:ok, name} where name is the localized display name.

  • {:error, exception} if the value is not found.

Examples

iex> Localize.Calendar.display_name(:calendar, :gregorian)
{:ok, "Gregorian Calendar"}

iex> Localize.Calendar.display_name(:calendar, :gregory, prefer: :menu)
{:ok, "Gregorian"}

iex> Localize.Calendar.display_name(:month, 1)
{:ok, "January"}

iex> Localize.Calendar.display_name(:month, 1, style: :abbreviated)
{:ok, "Jan"}

iex> Localize.Calendar.display_name(:day_of_week, 1)
{:ok, "Monday"}

iex> Localize.Calendar.display_name(:day_of_week, 1, style: :narrow)
{:ok, "M"}

iex> Localize.Calendar.display_name(:day_period, :am)
{:ok, "AM"}

iex> Localize.Calendar.display_name(:date_time_field, :year)
{:ok, "year"}

iex> Localize.Calendar.display_name(:era, 1)
{:ok, "Anno Domini"}

iex> Localize.Calendar.display_name(:quarter, 1, style: :abbreviated)
{:ok, "Q1"}

display_name!(type, value, options \\ [])

@spec display_name!(
  :calendar
  | :era
  | :quarter
  | :month
  | :day_of_week
  | :day_period
  | :date_time_field,
  term(),
  Keyword.t()
) :: String.t()

Same as display_name/3 but raises on error.

Arguments

  • type is the type of calendar item (:calendar, :era, :quarter, :month, :day_of_week, :day_period, or :date_time_field). See display_name/3.

  • value is the value to look up. The type depends on the type argument.

  • options is a keyword list of options.

Options

See display_name/3 for the supported options.

Returns

  • The localized display name as a string.

  • Raises an exception if the value is not found.

Examples

iex> Localize.Calendar.display_name!(:month, 1)
"January"

iex> Localize.Calendar.display_name!(:quarter, 1, style: :abbreviated)
"Q1"

eras(locale, calendar_type \\ :gregorian)

@spec eras(Localize.locale(), atom()) :: {:ok, map()} | {:error, Exception.t()}

Returns the era names for a locale and calendar type.

Arguments

  • locale is a locale identifier atom, string, or Localize.LanguageTag.t/0.

  • calendar_type is a CLDR calendar type atom. The default is :gregorian.

Returns

  • {:ok, era_data} where era_data is a map keyed by format (:abbreviated, :wide, :narrow) and era index.

  • {:error, exception} if the locale or calendar is not found.

Examples

iex> {:ok, eras} = Localize.Calendar.eras(:en)
iex> get_in(eras, [:abbreviated, 1])
"AD"

first_day_for_locale(language_tag)

@spec first_day_for_locale(Localize.locale()) :: integer() | {:error, Exception.t()}

Returns the first day of the week for a locale.

The day is found as TR35's first day algorithm finds it: a -u-fw- day, else the first day of a -u-rg- region, else Monday for the -u-ca-iso8601 calendar, else the first day of the locale's region, of its -u-sd- subdivision's region, of the region its likely subtags add, or of the world.

Arguments

Returns

  • An integer from 1 to 7 (Monday is 1).

  • {:error, exception} if the locale is invalid.

Examples

iex> Localize.Calendar.first_day_for_locale(:en)
7

iex> Localize.Calendar.first_day_for_locale("en-u-fw-mon")
1

iex> Localize.Calendar.first_day_for_locale("en-u-rg-gbzzzz")
1

iex> Localize.Calendar.first_day_for_locale("en-u-ca-iso8601")
1

first_day_for_territory(territory)

@spec first_day_for_territory(atom()) :: integer() | {:error, Exception.t()}

Returns the first day of the week for a territory.

Day numbers follow ISO 8601: 1 = Monday through 7 = Sunday.

Arguments

  • territory is a territory atom (e.g., :US, :GB).

Returns

  • An integer from 1 to 7.

  • {:error, exception} if territory is not an atom.

Examples

iex> Localize.Calendar.first_day_for_territory(:US)
7

iex> Localize.Calendar.first_day_for_territory(:GB)
1

known_calendars()

@spec known_calendars() :: [atom(), ...]

Returns the list of known CLDR calendar types.

Returns

  • A list of calendar type atoms.

Examples

iex> calendars = Localize.Calendar.known_calendars()
iex> :gregorian in calendars and :buddhist in calendars and :hebrew in calendars
true

localize(datetime, part, options \\ [])

@spec localize(map(), part(), Keyword.t()) ::
  {:ok, String.t() | [{1..7, String.t()}]} | {:error, Exception.t()}

Returns a localized string for a part of a date or time.

A month is named by its calendar: its cldr_month/2 gives the CLDR month whose name it takes, so a year that begins in July names its first month July, and the Hebrew and lunisolar calendars name each month whatever its place in the year. A leap month takes CLDR's leap-year name for its month (the Hebrew "Adar II"), or its month's name in the calendar's leap-month pattern (the Chinese "Second Monthbis"). A date's calendar is Calendar.ISO or one implementing the Calendrical behaviour, which answers these questions; any other is refused.

A part is named from the fields of the value it is asked of: an era from the year, a quarter from the year and the month, a month from the month, a day of the week from the year, the month and the day, and a day period from the hour. A value that lacks one of them has no such part, and is an error naming the field, as a pattern that asks for the part is in Localize.Date.to_string/2.

Arguments

  • datetime is any Date.t/0, Time.t/0, DateTime.t/0, or NaiveDateTime.t/0, or a map with the fields part is named from.

  • part is one of :era, :quarter, :month, :day_of_week, :days_of_week, or :day_period.

  • options is a keyword list of options. The default is [].

Options

  • :locale is a locale identifier. The default is Localize.get_locale().

  • :style is the display width. One of :wide (default), :abbreviated, :narrow, or :short. Not all widths exist for all parts — only the day parts carry :short — and a width the part does not have returns an error listing the widths it does.

  • :context is one of :format or :stand_alone. The default is :format.

  • :era — if set to :variant, uses variant era names ("Common Era" instead of "Anno Domini" in English).

  • :day_period — if set to :variant, uses variant day period names ("am"/"pm" instead of "AM"/"PM" in English). Each variant option is named for the part it applies to.

Returns

  • {:ok, name} where name is the localized string.

  • {:ok, days} where days is a list of {day_number, day_name} tuples, when part is :days_of_week.

  • {:error, %Localize.UnknownCalendarError{}} if the date's calendar cannot answer for its parts.

  • {:error, %Localize.DateTimeInvalidInputError{}} if the value lacks a field the part is named from, or holds one that is not an integer.

  • {:error, exception} if the part cannot be localized.

Examples

iex> Localize.Calendar.localize(~D[2019-06-01], :month)
{:ok, "June"}

iex> {:error, error} = Localize.Calendar.localize(%{year: 2019}, :month)
iex> error.missing
[:month]

iex> Localize.Calendar.localize(~D[2019-06-01], :month, style: :abbreviated)
{:ok, "Jun"}

iex> Localize.Calendar.localize(~D[2019-06-01], :day_of_week)
{:ok, "Saturday"}

iex> Localize.Calendar.localize(~D[2019-01-01], :era)
{:ok, "Anno Domini"}

iex> Localize.Calendar.localize(~D[2019-01-01], :era, era: :variant)
{:ok, "Common Era"}

iex> Localize.Calendar.localize(~D[2019-01-01], :quarter)
{:ok, "1st quarter"}

localize!(datetime, part, options \\ [])

@spec localize!(map(), part(), Keyword.t()) :: String.t() | [{1..7, String.t()}]

Same as localize/3 but raises on error.

Arguments

Options

See localize/3 for the supported options.

Returns

  • The localized name, or the list of {day_number, day_name} tuples when part is :days_of_week.

  • Raises an exception if the part cannot be localized.

Examples

iex> Localize.Calendar.localize!(~D[2019-06-01], :month)
"June"

iex> Localize.Calendar.localize!(~D[2019-06-01], :month, style: :abbreviated)
"Jun"

min_days_for_locale(language_tag)

@spec min_days_for_locale(Localize.locale()) :: integer() | {:error, Exception.t()}

Returns the minimum days in the first week of the year for a locale.

The -u-ca-iso8601 calendar's weeks hold four days, as ISO 8601's do. Any other locale takes the minimum days of the region TR35's first day algorithm finds for it: a -u-rg- region, else the locale's region, its -u-sd- subdivision's region, the region its likely subtags add, or the world.

Arguments

Returns

  • An integer from 1 to 7.

  • {:error, exception} if the locale is invalid.

Examples

iex> Localize.Calendar.min_days_for_locale(:en)
1

iex> Localize.Calendar.min_days_for_locale(:de)
4

iex> Localize.Calendar.min_days_for_locale("en-u-ca-iso8601")
4

min_days_for_territory(territory)

@spec min_days_for_territory(atom()) :: integer() | {:error, Exception.t()}

Returns the minimum days in the first week of the year for a territory.

Arguments

  • territory is a territory atom.

Returns

  • An integer from 1 to 7.

  • {:error, exception} if territory is not an atom.

Examples

iex> Localize.Calendar.min_days_for_territory(:US)
1

iex> Localize.Calendar.min_days_for_territory(:GB)
4

month_patterns(locale, calendar_type \\ :gregorian)

@spec month_patterns(Localize.locale(), atom()) ::
  {:ok, map()} | {:error, Exception.t()}

Returns the month pattern data for a locale and calendar type.

Month patterns are used by some calendar systems (such as Chinese and Hebrew) that have leap months. The patterns define how to format month names in leap and non-leap contexts.

Arguments

  • locale is a locale identifier atom, string, or Localize.LanguageTag.t/0.

  • calendar_type is a CLDR calendar type atom. The default is :gregorian.

Returns

  • {:ok, month_pattern_data} where month_pattern_data is a map of month patterns keyed by context and format width.

  • {:error, exception} if the locale or calendar is not found.

Examples

iex> {:ok, patterns} = Localize.Calendar.month_patterns(:en, :chinese)
iex> get_in(patterns, [:format, :narrow, :leap])
[0, "b"]

months(locale, calendar_type \\ :gregorian)

@spec months(Localize.locale(), atom()) :: {:ok, map()} | {:error, Exception.t()}

Returns the month names for a locale and calendar type.

Arguments

  • locale is a locale identifier atom, string, or Localize.LanguageTag.t/0.

  • calendar_type is a CLDR calendar type atom. The default is :gregorian.

Returns

  • {:ok, month_data} where month_data is a map keyed by context (:format, :stand_alone), then format, then month number.

  • {:error, exception} if the locale or calendar is not found.

Examples

iex> {:ok, months} = Localize.Calendar.months(:en)
iex> get_in(months, [:format, :wide, 6])
"June"

quarters(locale, calendar_type \\ :gregorian)

@spec quarters(Localize.locale(), atom()) :: {:ok, map()} | {:error, Exception.t()}

Returns the quarter names for a locale and calendar type.

Arguments

  • locale is a locale identifier atom, string, or Localize.LanguageTag.t/0.

  • calendar_type is a CLDR calendar type atom. The default is :gregorian.

Returns

  • {:ok, quarter_data} where quarter_data is a map keyed by context (:format, :stand_alone), then format, then quarter number.

  • {:error, exception} if the locale or calendar is not found.

Examples

iex> {:ok, quarters} = Localize.Calendar.quarters(:en)
iex> get_in(quarters, [:format, :abbreviated, 2])
"Q2"

register_provider(module)

@spec register_provider(module() | nil) :: :ok

Registers the module that answers for the calendars an application supplies.

A CLDR calendar type names no calendar module of its own, and Localize ships Calendar.ISO alone. A value in another calendar is asked for the calendars of its own family, and a value in Calendar.ISO has no family to ask, so the provider answers for it: a locale's -u-ca- then names a calendar for any value. The library supplying the calendars registers itself as its application starts.

Arguments

  • module is the module answering calendar_from_cldr_calendar_type/1, which takes a CLDR calendar type and returns {:ok, calendar}. nil registers no provider.

Returns

  • :ok.

Examples

iex> previous = Localize.Calendar.calendar_provider()
iex> Localize.Calendar.register_provider(MyApp.Calendars)
:ok
iex> Localize.Calendar.calendar_provider()
MyApp.Calendars
iex> Localize.Calendar.register_provider(previous)
:ok

strftime_options!(options \\ [])

@spec strftime_options!(Keyword.t()) :: Keyword.t()

Returns a keyword list of options for use with Calendar.strftime/3.

The returned keyword list contains callback functions that produce localized month names, day names, and AM/PM indicators.

Calendar.strftime/3 passes a month-name callback the month number alone, so a month is named by that number. For a calendar whose month names do not follow a month's position in its year (the Hebrew and lunisolar calendars), name the month with localize/3 instead.

Arguments

  • options is a keyword list.

Options

  • :locale is a locale identifier. The default is :en.

  • :calendar_type is a CLDR calendar type atom. The default is :gregorian.

Returns

  • A keyword list with :am_pm_names, :month_names, :abbreviated_month_names, :day_of_week_names, and :abbreviated_day_of_week_names keys.

Examples

iex> options = Localize.Calendar.strftime_options!(locale: :en)
iex> options[:month_names].(6)
"June"

iex> options = Localize.Calendar.strftime_options!(locale: :de)
iex> options[:abbreviated_day_of_week_names].(1)
"Mo."

weekdays(territory)

@spec weekdays(atom()) :: [1..7, ...] | {:error, Exception.t()}

Returns the weekday numbers for a territory as a list of ISO day-of-week numbers.

Arguments

  • territory is a territory atom.

Returns

  • A list of integers from 1 to 7.

  • {:error, exception} if territory is not an atom.

Examples

iex> Localize.Calendar.weekdays(:US)
[1, 2, 3, 4, 5]

weekend(territory)

@spec weekend(atom()) :: [integer()] | {:error, Exception.t()}

Returns the weekend days for a territory as a list of ISO day-of-week numbers.

Arguments

  • territory is a territory atom.

Returns

  • A list of integers from 1 to 7.

  • {:error, exception} if territory is not an atom.

Examples

iex> Localize.Calendar.weekend(:US)
[6, 7]

iex> Localize.Calendar.weekend(:IL)
[5, 6]