Localize.Duration (Localize v1.1.1)

Copy Markdown View Source

Functions to create and format durations — the difference between two dates, times, or datetimes expressed in calendar units.

A duration is represented as years, months, days, hours, minutes, seconds, and microseconds. This is useful for producing human-readable strings like "11 months, 30 days" or numeric patterns like "37:48:12".

Creating durations

  • new/2 — calculates the duration between two dates, times, or datetimes.

  • new_from_seconds/1 — creates a duration from a number of seconds.

Formatting durations

  • to_string/2 — formats a duration as a localized string using unit names (e.g., "11 months, 30 days") via Localize.Unit and Localize.List.

  • to_time_string/2 — formats the time portion of a duration using a pattern like "hh:mm:ss". Hours are unbounded (e.g., "37:48:12" for 37 hours).

Summary

Types

A date, time, naive datetime, or datetime.

t()

Duration in calendar units.

Functions

Calculates the calendar duration of a Date.Range.t/0.

Calculates the calendar duration between two dates, times, or datetimes.

Same as new/2 but raises on error.

Creates a duration from a number of seconds.

Formats a duration into typed parts, mirroring ECMA-402's formatToParts for Intl.DurationFormat.

Same as to_parts/2 but raises on error.

Formats a duration as a localized string using unit names.

Same as to_string/2 but raises on error.

Formats the time portion of a duration using a numeric pattern like "hh:mm:ss".

Types

date_or_time_or_datetime()

@type date_or_time_or_datetime() ::
  Calendar.date()
  | Calendar.time()
  | Calendar.datetime()
  | Calendar.naive_datetime()

A date, time, naive datetime, or datetime.

t()

@type t() :: %Localize.Duration{
  day: non_neg_integer(),
  hour: non_neg_integer(),
  microsecond: {integer(), 1..6},
  minute: non_neg_integer(),
  month: non_neg_integer(),
  second: non_neg_integer(),
  year: non_neg_integer()
}

Duration in calendar units.

Functions

new(range)

@spec new(Date.Range.t()) :: {:ok, t()} | {:error, Exception.t() | atom()}

Calculates the calendar duration of a Date.Range.t/0.

Equivalent to new(range.first, range.last).

Arguments

Returns

  • {:ok, duration} where duration is a t/0 struct.

  • {:error, exception} if the range endpoints are incompatible.

Examples

iex> {:ok, d} = Localize.Duration.new(Date.range(~D[2019-01-01], ~D[2019-12-31]))
iex> d.month
11

new(from, to)

@spec new(from :: date_or_time_or_datetime(), to :: date_or_time_or_datetime()) ::
  {:ok, t()} | {:error, Exception.t() | atom()}

Calculates the calendar duration between two dates, times, or datetimes.

Arguments

  • from is a date, time, or datetime representing the start.

  • to is a date, time, or datetime representing the end.

Returns

  • {:ok, duration} where duration is a t/0 struct.

  • {:error, exception} if the arguments are incompatible.

Examples

iex> {:ok, d} = Localize.Duration.new(~D[2019-01-01], ~D[2019-12-31])
iex> d.month
11

iex> {:ok, d} = Localize.Duration.new(~T[10:00:00], ~T[12:30:45])
iex> {d.hour, d.minute, d.second}
{2, 30, 45}

new!(from, to)

@spec new!(from :: date_or_time_or_datetime(), to :: date_or_time_or_datetime()) ::
  t() | no_return()

Same as new/2 but raises on error.

Arguments

  • from is a date, time, or datetime representing the start.

  • to is a date, time, or datetime representing the end.

Returns

  • A t/0 duration struct.

  • Raises an exception if the arguments are incompatible.

Examples

iex> d = Localize.Duration.new!(~D[2019-01-01], ~D[2019-12-31])
iex> d.month
11

new_from_seconds(seconds)

@spec new_from_seconds(seconds :: number()) :: t()

Creates a duration from a number of seconds.

The duration will contain only hours, minutes, seconds, and microseconds (year/month/day will be zero).

Arguments

  • seconds is a number of seconds (integer or float).

Returns

Examples

iex> d = Localize.Duration.new_from_seconds(136_092)
iex> {d.hour, d.minute, d.second}
{37, 48, 12}

iex> d = Localize.Duration.new_from_seconds(90.5)
iex> {d.minute, d.second}
{1, 30}

to_parts(duration, options \\ [])

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

Formats a duration into typed parts, mirroring ECMA-402's formatToParts for Intl.DurationFormat.

The parts concatenate to exactly the string to_string/2 produces with the same options. Each duration field contributes its unit parts (from Localize.Unit.to_parts/2) with the numeric segments carrying a :unit key naming the field; the list separators between fields are :literal parts.

Arguments

  • duration is a t/0 struct.

  • 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; numeric parts also carry a :unit key.

  • {:error, exception} if formatting fails.

Examples

iex> duration = %Localize.Duration{hour: 2, minute: 30}
iex> Localize.Duration.to_parts(duration, locale: :en)
{:ok,
 [
   %{type: :integer, value: "2", unit: :hour},
   %{type: :literal, value: " "},
   %{type: :unit, value: "hours"},
   %{type: :literal, value: ", "},
   %{type: :integer, value: "30", unit: :minute},
   %{type: :literal, value: " "},
   %{type: :unit, value: "minutes"}
 ]}

to_parts!(duration, options \\ [])

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

Same as to_parts/2 but raises on error.

Arguments

  • duration is a t/0 struct.

  • 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 formatting fails.

Examples

iex> Localize.Duration.to_parts!(%Localize.Duration{hour: 2}, locale: :en) |> length()
3

to_string(duration, options \\ [])

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

Formats a duration as a localized string using unit names.

Non-zero duration parts are formatted as units and joined with the locale's unit list pattern for the requested width, per ECMA-402 Intl.DurationFormat (e.g., "11 months, 30 days").

Arguments

  • duration is a t/0 struct.

  • options is a keyword list of options.

Options

  • :except is a list of time unit atoms to omit from the output (e.g., [:microsecond]). The default is [:microsecond].

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

  • :format is the display width applied to every unit: one of :long ("11 months, 30 days"), :short ("11 mths, 30 days"), or :narrow ("11m 30d"). The default is :long. It also selects the CLDR unit list pattern that joins the parts.

  • :display is a keyword list of per-unit display control, mirroring ECMA-402's per-unit *Display options. Each key is a unit atom (:year, :month, :day, :hour, :minute, :second, :microsecond) and each value is :auto (omit the unit when zero, the default) or :always (render the unit even when zero).

  • :formats is a keyword list of per-unit width overrides, mirroring ECMA-402's per-unit width options. Each key is a unit atom (the same set as :display) and each value is :long, :short, or :narrow, overriding :format for that unit alone; units not named keep :format. Note the plural: :format sets the width for the whole duration, :formats overrides individual units within it.

Returns

  • {:ok, formatted_string} on success.

  • {:error, exception} if formatting fails.

Examples

iex> {:ok, d} = Localize.Duration.new(~D[2019-01-01], ~D[2019-12-31])
iex> Localize.Duration.to_string(d, locale: :en)
{:ok, "11 months, 30 days"}

iex> {:ok, d} = Localize.Duration.new(~D[2019-01-01], ~D[2019-12-31])
iex> Localize.Duration.to_string(d, locale: :en, format: :narrow)
{:ok, "11m 30d"}

iex> duration = %Localize.Duration{hour: 2}
iex> Localize.Duration.to_string(duration, locale: :en, display: [minute: :always])
{:ok, "2 hours, 0 minutes"}

iex> duration = %Localize.Duration{hour: 2, minute: 30}
iex> Localize.Duration.to_string(duration, locale: :en, formats: [hour: :narrow])
{:ok, "2h, 30 minutes"}

to_string!(duration, options \\ [])

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

Same as to_string/2 but raises on error.

Arguments

  • duration is a t/0 struct.

  • options is a keyword list of options.

Options

See to_string/2 for the supported options.

Returns

  • The formatted duration as a string.

  • Raises an exception if formatting fails.

Examples

iex> {:ok, d} = Localize.Duration.new(~D[2019-01-01], ~D[2019-12-31])
iex> Localize.Duration.to_string!(d, locale: :en)
"11 months, 30 days"

to_time_string(duration, options \\ [])

@spec to_time_string(t(), Keyword.t()) :: {:ok, String.t()}

Formats the time portion of a duration using a numeric pattern like "hh:mm:ss".

Hours are unbounded — a duration of 37 hours, 48 minutes, and 12 seconds formats as "37:48:12".

Arguments

  • duration is a t/0 struct.

  • options is a keyword list of options.

Options

  • :format is a format pattern string. The default is "hh:mm:ss". Use "h:mm:ss" for no zero-padding on hours, or "mm:ss" for minutes and seconds only.

Returns

  • {:ok, formatted_string} on success.

Examples

iex> d = Localize.Duration.new_from_seconds(136_092)
iex> Localize.Duration.to_time_string(d)
{:ok, "37:48:12"}

iex> d = Localize.Duration.new_from_seconds(65)
iex> Localize.Duration.to_time_string(d, format: "m:ss")
{:ok, "1:05"}

to_time_string!(duration, options \\ [])

@spec to_time_string!(t(), Keyword.t()) :: String.t()

Same as to_time_string/2 but raises on error.

Arguments

  • duration is a t/0 struct.

  • options is a keyword list of options.

Options

See to_time_string/2 for the supported options.

Returns

  • The formatted time portion of the duration as a string.

  • Raises an exception if formatting fails.

Examples

iex> d = Localize.Duration.new_from_seconds(136_092)
iex> Localize.Duration.to_time_string!(d)
"37:48:12"

iex> d = Localize.Duration.new_from_seconds(65)
iex> Localize.Duration.to_time_string!(d, format: "m:ss")
"1:05"