Localize.Date (Localize v1.4.0)

Copy Markdown View Source

Provides localized formatting of Date structs and date-like maps.

Supports both full dates (%{year: _, month: _, day: _}) and partial dates (any map with one or more of :year, :month, :day). For a partial date a standard format, or no format, derives the skeleton from the fields present; a skeleton or pattern that asks for a field the date does not have returns Localize.DateTimeInvalidInputError.

Formats are defined in CLDR and described in TR35.

Ordinal days are a technical preview

CLDR 49 adds the ddd field, which formats the day as a date ordinal taken from the locale's dayOfMonths data — :yMMMddd renders "Jul 6th, 2024" in en and "1er juil. 2024" in fr. A locale without that data, and any pattern whose month is numeric, format the plain day.

TR35 designates the dayOfMonth section a technical preview, and the element shape was narrowed once during CLDR 49's development. Only the abbreviated width and the ordinal-keyed forms are read, and Localize.Interval cannot yet request an ordinal skeleton. Treat both the output and the surface as subject to change.

Summary

Functions

Parses a localized date string.

Formats a date into typed parts, mirroring ECMA-402's formatToParts.

Same as to_parts/2 but raises on error.

Formats a date according to a CLDR format pattern.

Same as to_string/2 but raises on error.

Functions

parse(string, options \\ [])

@spec parse(String.t(), Keyword.t()) :: {:ok, Date.t()} | {:error, Exception.t()}

Parses a localized date string.

Accepts any shape the locale accepts, including the locale's CLDR short, medium, long and full patterns and ISO 8601.

A date in another calendar is parsed by passing that calendar's module as :calendar; the companion calendrical package supplies the calendars Localize formats for.

Arguments

  • string is a string in any shape the locale accepts, including the locale's CLDR short, medium, long and full patterns and ISO 8601.

  • options is a keyword list of options.

Options

  • :locale is a locale identifier. The default is the locale returned by Localize.get_locale/0.

  • :calendar is a calendar module, such as Calendar.ISO (the default), Calendrical.Gregorian or Calendrical.Hebrew. The input is read with the locale's patterns for the calendar's CLDR type, and the date is built and returned in this module. A week date, in any form ISO 8601 writes one in ("2024-W05-4", "2024W054" and the week alone, "2024-W05"), is the calendar's own: every calendar answers date_from_week_date/3, so it is ISO 8601's week for Calendar.ISO and the fifth week of its own year for a calendar built of weeks. Text that none of the calendar's own formats reads is read in the calendar its info/0 names as :parsing_calendar, and converted: a calendar built of weeks, whose months are "M02" and not "Feb", names Calendar.ISO, so "Feb 1, 2024" is 1 February 2024 in it. A composite calendar, whose dates are written with the formats of whichever of its calendars was in effect, names those calendars with its parsing_calendars/0, and a date is then read in each and converted, held to the calendar its day is written in. A calendar's own formats come before ISO 8601: a year, a month and a day between hyphens that any of them reads, as CLDR's root short date of the Chinese calendar does (r-MM-dd), is the calendar's own date, and where none does it is an ISO 8601 date, converted into the calendar. Anything that is not a calendar module, including a CLDR calendar name such as :hebrew or "gregorian", and a module that implements only the Calendar behaviour, returns a Localize.UnknownCalendarError.t/0.

  • :format is the format the text was written with, as to_string/2 takes it: a standard format (:short, :medium, :long or :full), a skeleton atom such as :yMd, a Localize.DateTime.SemanticSkeleton or a pattern string such as "d/M/y". The text is read with that format and no other, after the calendar's own notation, so a date written by a skeleton whose fields stand in another order than the locale's standard formats' reads back as itself: mt's :yMd writes 3 April 2024 as "4/3/2024", which is 4 March where no format is given. A pattern string is read before the notation, which is never what it writes, and the notation where the pattern reads nothing. A format of fewer fields than a date has, such as :yMMM, needs as: :map. The default is nil: the text is read in whichever of the locale's formats reads it first.

  • :reference_date is the Date.t/0 that partial input is completed against, taken in the calendar the input is read in. A week written without its year is a week of the reference date's week-based year, which is not the year of its days about the new year. The default is today.

  • :as is :struct or :map. :map returns only the fields the input actually carried, rather than completing them. They must still be fields some date has, so "June 31" is an error in both forms while "February 29" is a partial date. A date read in another calendar and converted, as a composite calendar reads one of an earlier calendar, comes back whole, as a partial date has no fields in the other calendar. What names no day to convert is the exception: a year is %{year: 2026}, and a year and a quarter are the two. The default is :struct.

Returns

Examples

iex> Localize.Date.parse("22.03.2026", locale: :de)
{:ok, ~D[2026-03-22]}

iex> Localize.Date.parse("March 22, 2026", locale: :en)
{:ok, ~D[2026-03-22]}

iex> Localize.Date.parse("4/3/2024", locale: :en)
{:ok, ~D[2024-04-03]}

iex> Localize.Date.parse("4/3/2024", locale: :en, format: "d/M/y")
{:ok, ~D[2024-03-04]}

to_parts(date, options \\ [])

@spec to_parts(map(), Keyword.t()) ::
  {:ok, [%{type: atom(), value: String.t()}]} | {:error, Exception.t()}

Formats a date into typed parts, mirroring ECMA-402's formatToParts.

The parts concatenate to exactly the string to_string/2 produces with the same options. Each pattern field is tagged with its type: :year, :month, :day, :weekday, :era, and :literal for separators.

Arguments

  • date is a Date.t/0 or any map with date keys.

  • options is a keyword list of options.

Options

See to_string/2 for the supported options.

Returns

  • {:ok, parts} where parts is a list of %{type: atom(), value: String.t()} maps.

  • {:error, exception} if the date cannot be formatted.

Examples

iex> Localize.Date.to_parts(~D[2017-07-10], locale: :en)
{:ok,
 [
   %{type: :month, value: "Jul"},
   %{type: :literal, value: " "},
   %{type: :day, value: "10"},
   %{type: :literal, value: ", "},
   %{type: :year, value: "2017"}
 ]}

to_parts!(date, options \\ [])

@spec to_parts!(map(), Keyword.t()) :: [%{type: atom(), value: String.t()}]

Same as to_parts/2 but raises on error.

Arguments

  • date is a Date.t/0 or any map with date keys.

  • options is a keyword list of options. See to_parts/2.

Returns

  • A list of %{type: atom(), value: String.t()} maps.

Raises

  • Raises an exception if the date cannot be formatted.

Examples

iex> Localize.Date.to_parts!(~D[2017-07-10], locale: :en) |> length()
5

to_string(date, options \\ [])

@spec to_string(map(), Keyword.t()) :: {:ok, String.t()} | {:error, Exception.t()}

Formats a date according to a CLDR format pattern.

Arguments

  • date is a Date.t/0 or any map with one or more of :year, :month, :day keys.

  • options is a keyword list of options.

Options

  • :format is a standard format name (:short, :medium, :long, :full), a format skeleton atom, a Localize.DateTime.SemanticSkeleton or a format pattern string. The default is :medium. For a partial date a standard format derives its skeleton from the fields present, with the month numeric at :short, abbreviated at :medium and wide at :long and :full. Every calendar's date is written from its year, its month and its day: a calendar built of weeks, such as Calendrical.ISOWeek, has the months of its pattern of weeks, named as CLDR's generic calendar names them ("M06 16, 2026 AD"), and its week is written by a format that names one (:yw, "week 25 of 2026").

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

  • :number_system is a CLDR numbering system name (for example, :thai). All numeric fields render in that system; a -u-nu- locale extension may be used instead. The default is the locale's number system.

  • :numeric_date_separator is a string replacing the locale's numericDateSeparator wherever it separates the fields of a numeric-month date, as TR35 allows an implementation to offer. Localize.DateTime.numeric_separators/2 returns the locale's own. The default is the locale's separator.

  • :numeric_time_separator is a string replacing the locale's numericTimeSeparator wherever it separates time fields. The default is the locale's separator.

  • :prefer selects between CLDR alt variants. Accepts an atom or a list of atoms in priority order. Recognised values: :standard / :variant (locales like en-CA publish both an ISO pattern "y-MM-dd" and a locale-variant "d/M/yy"), and :unicode / :ascii (NBSP and curly quotes vs ASCII). Examples: prefer: :variant, prefer: [:variant, :ascii]. The default is [:standard, :unicode].

Returns

  • {:ok, formatted_string} on success.

  • {:error, exception} if the date cannot be formatted.

Examples

iex> Localize.Date.to_string(~D[2017-07-10], locale: :en)
{:ok, "Jul 10, 2017"}

iex> Localize.Date.to_string(~D[2017-07-10], format: :full, locale: :en)
{:ok, "Monday, July 10, 2017"}

iex> Localize.Date.to_string(~D[2017-07-10], format: :short, locale: :en)
{:ok, "7/10/17"}

iex> Localize.Date.to_string(~D[2017-07-10], format: :short, locale: :fr)
{:ok, "10/07/2017"}

iex> Localize.Date.to_string(%{year: 2024, month: 6}, format: :yMMM, locale: :fr)
{:ok, "juin 2024"}

iex> Localize.Date.to_string(%{year: 2024, month: 6}, format: :long, locale: :en)
{:ok, "June 2024"}

to_string!(date, options \\ [])

@spec to_string!(map(), Keyword.t()) :: String.t()

Same as to_string/2 but raises on error.

Arguments

  • date is a Date.t/0 or any map with one or more of :year, :month, :day keys.

  • options is a keyword list of options.

Options

See to_string/2 for the supported options.

Returns

  • A formatted string.

  • Raises an exception if the date cannot be formatted.

Examples

iex> Localize.Date.to_string!(~D[2017-07-10], locale: :en)
"Jul 10, 2017"

iex> Localize.Date.to_string!(%{year: 2024, month: 6}, format: :yMMM, locale: :fr)
"juin 2024"