Localize.Time (Localize v1.4.0)

Copy Markdown View Source

Provides localized formatting of Time structs and time-like maps.

Supports both full times (%{hour: _, minute: _, second: _}) and partial times (any map with one or more of :hour, :minute, :second). For a partial time a standard format, or no format, derives the skeleton from the fields present, with the hour in the locale's hour cycle; a skeleton or pattern that asks for a field the time does not have returns Localize.DateTimeInvalidInputError.

Formats are defined in CLDR and described in TR35.

Summary

Functions

Returns the locale's preferred hour cycle.

Parses a localized time string.

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

Same as to_parts/2 but raises on error.

Formats a time according to a CLDR format pattern.

Same as to_string/2 but raises on error.

Functions

hour_format_from_locale(language_tag)

@spec hour_format_from_locale(Localize.LanguageTag.t() | atom() | String.t()) ::
  {:ok, :h11 | :h12 | :h23 | :h24} | {:error, Exception.t()}

Returns the locale's preferred hour cycle.

CLDR ships a per-territory (and per locale-territory) preference for how time-of-day is presented. The four cycles are:

AtomRangeDescription
:h110–1112-hour clock, midnight is 0
:h121–1212-hour clock, midnight is 12
:h230–2324-hour clock, midnight is 0
:h241–2424-hour clock, midnight is 24

A -u-hc- Unicode extension on the locale (e.g. "fr-u-hc-h12") overrides the territory default. CLDR 49's technical-preview c12 and c24 ask for the locale's own 12-hour or 24-hour cycle, which TR35 resolves from the cycles the region allows: c12 is :h11 where K is allowed before h, as in Japan, and :h12 otherwise.

Arguments

Returns

  • {:ok, hour_cycle} where hour_cycle is one of :h11, :h12, :h23, :h24.

  • {:error, exception} if the locale cannot be validated.

Examples

iex> Localize.Time.hour_format_from_locale(:ja)
{:ok, :h23}

iex> Localize.Time.hour_format_from_locale("en-AU")
{:ok, :h12}

iex> Localize.Time.hour_format_from_locale("fr-u-hc-h12")
{:ok, :h12}

iex> Localize.Time.hour_format_from_locale("ja-u-hc-c12")
{:ok, :h11}

iex> Localize.Time.hour_format_from_locale("en-US-u-hc-c24")
{:ok, :h23}

hour_format_from_locale!(locale)

@spec hour_format_from_locale!(Localize.LanguageTag.t() | atom() | String.t()) ::
  :h11 | :h12 | :h23 | :h24

Same as hour_format_from_locale/1 but raises on error.

Arguments

Returns

  • :h11, :h12, :h23 or :h24.

Raises the exception hour_format_from_locale/1 returns.

Examples

iex> Localize.Time.hour_format_from_locale!(:ja)
:h23

parse(string, options \\ [])

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

Parses a localized time string.

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

ISO 8601 is read in every locale: a time between colons, with its seconds or without them ("14:30:45", "14:30"), and, after its time designator T, a time without its minutes or without its separators ("T14", "T1430", "T143045"). Digits alone are not read as ISO 8601 without the T: an hour by itself is the locale's to read, and "1430" is no time. A fraction is the second's alone.

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 the calendar module the time is written for, whose time formats are read before the Gregorian calendar's. The default is Calendar.ISO. Anything that is not a calendar module, a CLDR calendar type included, is 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 :Hm, a Localize.DateTime.SemanticSkeleton or a pattern string such as "HH'h'mm". The text is read with that format and no other, ISO 8601 included. A :long or a :full format reads a time with its zone and, as it is written for a value that has none, without it, and a semantic skeleton whose minutes are optional reads a time on the hour written without them. The default is nil: the text is read as ISO 8601 or in whichever of the locale's formats reads it first.

  • :as is :struct or :map. :map returns only the fields the input actually carried, rather than completing them; a minute or second no time has is an error in both forms. A fixed offset (GMT+5) adds the DateTime.t/0 zone fields (:time_zone, :utc_offset, :std_offset and :zone_abbr); a named zone, whose offset depends on a date, stays in :time_zone as written. The default is :struct.

Returns

Examples

iex> Localize.Time.parse("14:30", locale: :de)
{:ok, ~T[14:30:00]}

iex> Localize.Time.parse("2:30 PM", locale: :en)
{:ok, ~T[14:30:00]}

iex> Localize.Time.parse("T1430", locale: :fi)
{:ok, ~T[14:30:00]}

iex> Localize.Time.parse("14h30", locale: :en, format: "HH'h'mm")
{:ok, ~T[14:30:00]}

to_parts(time, options \\ [])

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

Formats a time 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: :hour, :minute, :second, :fractional_second, :day_period, :time_zone_name, and :literal for separators.

Arguments

  • time is a Time.t/0 or any map with time 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 time cannot be formatted.

Examples

iex> Localize.Time.to_parts(~T[14:30:05], locale: :en, format: "HH:mm")
{:ok,
 [
   %{type: :hour, value: "14"},
   %{type: :literal, value: ":"},
   %{type: :minute, value: "30"}
 ]}

to_parts!(time, options \\ [])

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

Same as to_parts/2 but raises on error.

Arguments

  • time is a Time.t/0 or any map with time 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 time cannot be formatted.

Examples

iex> Localize.Time.to_parts!(~T[14:30:05], locale: :en, format: "HH:mm") |> length()
3

to_string(time, options \\ [])

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

Formats a time according to a CLDR format pattern.

Arguments

  • time is a Time.t/0 or any map with one or more of :hour, :minute, :second 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 full times. For a partial time a standard format, or no format, derives its skeleton from the fields present, with the hour in the locale's hour cycle or its -u-hc- override. A value with no time zone, a Time.t/0, a NaiveDateTime.t/0 or a map holding neither :time_zone nor :utc_offset, has nothing to write the zone field of :long and :full with, so those formats write their other fields as the locale writes them alone: ja's full time is "10:30:00", where a time in Tokyo is "10時30分00秒 日本標準時".

  • :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: :unicode / :ascii (NBSP and curly quotes vs ASCII) and :standard / :variant (a few locales publish two preferred forms). Examples: prefer: :ascii, prefer: [:variant, :ascii]. The default is [:standard, :unicode].

Returns

  • {:ok, formatted_string} on success.

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

Examples

iex> Localize.Time.to_string(~T[14:30:00], locale: :en, prefer: :ascii)
{:ok, "2:30:00 PM"}

iex> Localize.Time.to_string(~T[14:30:00], format: :short, locale: :en, prefer: :ascii)
{:ok, "2:30 PM"}

iex> Localize.Time.to_string(%{hour: 14, minute: 30}, format: :hm, locale: :en, prefer: :ascii)
{:ok, "2:30 PM"}

iex> Localize.Time.to_string(%{hour: 14, minute: 30}, locale: :de)
{:ok, "14:30"}

to_string!(time, options \\ [])

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

Same as to_string/2 but raises on error.

Arguments

  • time is a Time.t/0 or any map with one or more of :hour, :minute, :second keys.

  • options is a keyword list of options.

Options

See to_string/2 for the supported options.

Returns

  • The formatted time as a string.

  • Raises an exception if the time cannot be formatted.

Examples

iex> Localize.Time.to_string!(~T[14:30:00], locale: :en, prefer: :ascii)
"2:30:00 PM"