View Source Moar.Duration (Moar v1.12.0)

A duration is a {time, unit} tuple.

The time is a number and the unit is one of:

  • :nanosecond
  • :microsecond
  • :millisecond
  • :second
  • :minute
  • :hour
  • :day
  • :approx_month (30 days)
  • :approx_year (360 days)

Link to this section Summary

Functions

Returns the duration between datetime and now, in the largest possible unit.

Shifts duration to an approximately equal duration that's simpler. For example, {121, :second} would get shifted to {2, :minute}.

Returns the duration between earlier and later, in the largest possible unit.

Converts a {duration, time_unit} tuple into a numeric duration, rounding down to the nearest whole number.

Formats a duration in either a long or short style, with optional transformers and an optional suffix.

If possible, shifts duration to a higher time unit that is more readable to a human. Returns duration unchanged if it cannot be exactly shifted.

Shifts duration to time_unit. It is similar to convert/1 but this function returns a duration tuple, while convert/1 just returns an integer value.

Shortcut to format(duration, :long). See format/2.

Returns the list of duration unit names in descending order.

Link to this section Types

@type date_time_ish() :: DateTime.t() | NaiveDateTime.t() | binary()
@type format_style() :: :long | :short
@type format_transformer() :: :ago | :approx | :humanize
@type format_transformers() :: format_transformer() | [format_transformer()]
@type t() :: {time :: number(), unit :: time_unit()}
@type time_unit() ::
  :nanosecond
  | :microsecond
  | :millisecond
  | :second
  | :minute
  | :hour
  | :day
  | :approx_month
  | :approx_year

Link to this section Functions

@spec ago(date_time_ish()) :: t()

Returns the duration between datetime and now, in the largest possible unit.

datetime can be an ISO8601-formatted string, a DateTime, or a NaiveDateTime.

iex> DateTime.utc_now() |> Moar.DateTime.add({-121, :minute}) |> Moar.Duration.ago() |> Moar.Duration.shift(:minute)
{121, :minute}
@spec approx(t()) :: t()

Shifts duration to an approximately equal duration that's simpler. For example, {121, :second} would get shifted to {2, :minute}.

Warning

This function is lossy because it intentionally loses precision.

If the time value of the duration is exactly 1, the duration is returned unchanged: {1, :minute} => {1, :minute}. Otherwise, the duration is shifted to the highest unit where the time value is >= 2.

iex> Moar.Duration.approx({1, :minute})
{1, :minute}

iex> Moar.Duration.approx({7300, :second})
{2, :hour}
@spec between(date_time_ish(), date_time_ish()) :: t()

Returns the duration between earlier and later, in the largest possible unit.

earlier and later can be ISO8601-formatted strings, DateTimes, or NaiveDateTimes.

iex> earlier = ~U[2020-01-01T00:00:00.000000Z]
iex> later = ~U[2020-01-01T02:01:00.000000Z]
iex> Moar.Duration.between(earlier, later)
{121, :minute}
Link to this function

convert(duration, to_unit)

View Source
@spec convert(from :: t(), to :: time_unit()) :: number()

Converts a {duration, time_unit} tuple into a numeric duration, rounding down to the nearest whole number.

Warning

This function is lossy because it rounds down to the nearest whole number.

Uses System.convert_time_unit/3 under the hood; see its documentation for more details.

It is similar to shift/1 but this function returns an integer value, while shift/1 returns a duration tuple.

iex> Moar.Duration.convert({121, :second}, :minute)
2
Link to this function

format(duration, style_or_transformers_or_suffix \\ :long)

View Source
@spec format(t() | date_time_ish(), format_style() | format_transformer() | binary()) ::
  binary()

Formats a duration in either a long or short style, with optional transformers and an optional suffix.

(This describes format/2, format/3, and format/4).

  • The first parameter is a duration tuple, unless one of the transformers is :ago, in which case it can be a DateTime, NaiveDateTime, or an ISO8601-formatted string.
  • The next parameter is the style:
    • :long produces something like "25 seconds".
    • :short produces something like "25s".
    • If this parameter is omitted, :long format is used.
  • The next parameter is a transformer or a list of transformers, which can include:
    • :ago transforms via ago/1
    • :approx transforms via approx/1
    • :humanize transforms via humanize/1
    • If this parameter is omitted, no transformations are applied.
  • The next parameter is a suffix which, if specified, will be appended to the formatted result. If the :ago transformer is specified and a suffix is not specified, the suffix will default to "ago".

Not all parameters need to be specified; format({5, :minute}, "ago") is equivalent to format({5, :minute}, :long, [], "ago").

iex> Moar.Duration.format({1, :second})
"1 second"

iex> Moar.Duration.format({120, :second})
"120 seconds"

iex> Moar.Duration.format({120, :second}, :long)
"120 seconds"

iex> Moar.Duration.format({120, :second}, :short)
"120s"

iex> Moar.Duration.format({120, :second}, "yonder")
"120 seconds yonder"

iex> Moar.Duration.format({120, :second}, :humanize)
"2 minutes"

iex> Moar.Duration.format({120, :second}, :humanize, "yonder")
"2 minutes yonder"

iex> DateTime.utc_now()
...> |> Moar.DateTime.add({-310, :second})
...> |> Moar.Duration.format(:short, [:ago, :approx], "henceforth")
"5m henceforth"
Link to this function

format(duration_or_datetime, transformers, suffix)

View Source

See docs for format/2.

Link to this function

format(duration_or_datetime, style, transformers, suffix)

View Source
@spec format(
  t() | date_time_ish(),
  format_style(),
  format_transformers(),
  binary() | nil
) :: binary()

See docs for format/2.

@spec humanize(t()) :: t()

If possible, shifts duration to a higher time unit that is more readable to a human. Returns duration unchanged if it cannot be exactly shifted.

iex> Moar.Duration.humanize({60000, :millisecond})
{1, :minute}

iex> Moar.Duration.humanize({48, :hour})
{2, :day}

iex> Moar.Duration.humanize({49, :hour})
{49, :hour}
Link to this function

shift(duration, to_unit)

View Source
@spec shift(t(), time_unit()) :: t()

Shifts duration to time_unit. It is similar to convert/1 but this function returns a duration tuple, while convert/1 just returns an integer value.

Warning

This function is lossy because it rounds down to the nearest whole number.

iex> Moar.Duration.shift({121, :second}, :minute)
{2, :minute}
@spec to_string(t()) :: String.t()

Shortcut to format(duration, :long). See format/2.

@spec units() :: [time_unit()]

Returns the list of duration unit names in descending order.