View Source Moar.Duration (Moar v1.62.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)
Note
This module is naive and intentionally doesn't account for real-world calendars and all of their complexity, such as leap years, leap days, daylight saving time, past and future calendar oddities, etc.
As "Falsehoods programmers believe about time" says, "If you think you understand everything about time, you're probably doing it wrong."
See
Cldr.Calendar.Duration
for one example of a full-featured library that is far more likely to be correct.
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.
Returns the duration between now and datetime
, in the largest possible unit.
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.
Shifts duration
to the next smaller unit. Raises if it's already at the smallest unit (nanosecond).
Shifts duration
to the next larger unit. Raises if it's already at the largest unit (approx_year).
Rounds the result towards zero.
Shortcut to format(duration, :long)
. See format/4
.
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 time_unit() ::
:nanosecond
| :microsecond
| :millisecond
| :second
| :minute
| :hour
| :day
| :approx_month
| :approx_year
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
.
See also from_now/1
.
iex> DateTime.utc_now()
...> |> Moar.DateTime.subtract({121, :minute})
...> |> Moar.Duration.ago()
...> |> Moar.Duration.shift(:minute)
{121, :minute}
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, DateTime
s, or NaiveDateTime
s.
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}
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
format(duration_or_datetime, style_or_transformers_or_suffix \\ nil, transformers_or_suffix \\ nil, suffix \\ nil)
View Source@spec format( t() | date_time_ish(), format_style() | format_transformers() | binary() | nil, format_transformers() | binary() | nil, binary() | nil ) :: binary()
Formats a duration in either a long or short style, with optional transformers and an optional suffix.
- The first argument is a duration tuple, unless one of the transformers is
:ago
, in which case it can be aDateTime
,NaiveDateTime
, or an ISO8601-formatted string. - The second argument is optional and is the style, transformer, list of transformers, or suffix.
- The third argument is optional and is the transformer, list of transformers, or suffix.
- The fourth argument is optional and is the suffix.
Styles:
:long
, which formats like"25 seconds"
.:short
, which formats like"25s"
.- Defaults to
:long
Transformers:
:ago
transforms viaago/1
:approx
transforms viaapprox/1
:humanize
transforms viahumanize/1
- If no transformers are specified, no transformations are applied.
Suffix:
- A string that 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"
. To use the "ago" transformer with no suffix, specify an empty string as the suffix (nil
will not suffice).
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> Moar.Duration.format({310, :second})
"310 seconds"
iex> Moar.Duration.format({310, :second}, :approx)
"5 minutes"
iex> DateTime.utc_now()
...> |> Moar.DateTime.add({-310, :second})
...> |> Moar.Duration.format(:short, [:ago, :approx], "henceforth")
"5m henceforth"
@spec from_now(date_time_ish()) :: t()
Returns the duration between now and datetime
, in the largest possible unit.
datetime
can be an ISO8601-formatted string, a DateTime
, or a NaiveDateTime
.
See also ago/1
.
iex> DateTime.utc_now()
...> |> Moar.DateTime.add({121, :minute})
...> |> Moar.Duration.from_now()
...> |> Moar.Duration.approx()
{2, :hour}
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}
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}
Shifts duration
to the next smaller unit. Raises if it's already at the smallest unit (nanosecond).
iex> Moar.Duration.shift_down({1, :hour})
{60, :minute}
Shifts duration
to the next larger unit. Raises if it's already at the largest unit (approx_year).
Rounds the result towards zero.
Warning
This function is lossy because it rounds down to the nearest whole number.
iex> Moar.Duration.shift_up({60, :minute})
{1, :hour}
iex> Moar.Duration.shift_up({125, :minute})
{2, :hour}
Shortcut to format(duration, :long)
. See format/4
.