Predicator.Duration (predicator v5.0.0)

Copy Markdown View Source

Duration utilities for time span calculations in Predicator expressions.

This module provides functions to create, manipulate, and convert duration values for use in relative date expressions and date arithmetic.

Examples

iex> Predicator.Duration.new(days: 3, hours: 8)
%{years: 0, months: 0, weeks: 0, days: 3, hours: 8, minutes: 0, seconds: 0, milliseconds: 0}

iex> Predicator.Duration.from_units([{"3", "d"}, {"8", "h"}])
{:ok, %{years: 0, months: 0, weeks: 0, days: 3, hours: 8, minutes: 0, seconds: 0, milliseconds: 0}}

iex> Predicator.Duration.to_seconds(%{days: 1, hours: 2, minutes: 30})
95400

Summary

Functions

Adds a duration to a Date, returning a Date.

Adds a duration to a DateTime, returning a DateTime.

Adds a specific unit amount to a duration.

Creates a duration from parsed unit pairs.

Creates a new duration with specified time units.

Parses a duration literal string into a duration map.

Subtracts a duration from a Date, returning a Date.

Subtracts a duration from a DateTime, returning a DateTime.

Converts a duration to total milliseconds (approximate for months and years).

Converts a duration to total seconds (approximate for months and years).

Converts a duration to a human-readable string.

Functions

add_to_date(date, duration)

@spec add_to_date(Date.t(), Predicator.Types.duration()) :: Date.t()

Adds a duration to a Date, returning a Date.

Examples

iex> date = ~D[2024-01-15]
iex> duration = Predicator.Duration.new(days: 3, weeks: 1)
iex> Predicator.Duration.add_to_date(date, duration)
~D[2024-01-25]

add_to_datetime(datetime, duration)

@spec add_to_datetime(DateTime.t(), Predicator.Types.duration()) :: DateTime.t()

Adds a duration to a DateTime, returning a DateTime.

Examples

iex> datetime = ~U[2024-01-15T10:30:00Z]
iex> duration = Predicator.Duration.new(days: 2, hours: 3, minutes: 30)
iex> Predicator.Duration.add_to_datetime(datetime, duration)
~U[2024-01-17T14:00:00Z]

add_unit(duration, unit, value)

Adds a specific unit amount to a duration.

Examples

iex> duration = Predicator.Duration.new(days: 1)
iex> Predicator.Duration.add_unit(duration, "h", 3)
%{years: 0, months: 0, weeks: 0, days: 1, hours: 3, minutes: 0, seconds: 0, milliseconds: 0}

from_units(unit_pairs)

@spec from_units([{binary(), binary()}]) ::
  {:ok, Predicator.Types.duration()} | {:error, binary()}

Creates a duration from parsed unit pairs.

Takes a list of {value, unit} tuples and converts them to a duration.

Examples

iex> Predicator.Duration.from_units([{"3", "d"}, {"8", "h"}])
{:ok, %{years: 0, months: 0, weeks: 0, days: 3, hours: 8, minutes: 0, seconds: 0, milliseconds: 0}}

iex> Predicator.Duration.from_units([{"invalid", "d"}])
{:error, "Invalid duration value: invalid"}

new(opts \\ [])

Creates a new duration with specified time units.

All unspecified units default to 0.

Examples

iex> Predicator.Duration.new(days: 2, hours: 3)
%{years: 0, months: 0, weeks: 0, days: 2, hours: 3, minutes: 0, seconds: 0, milliseconds: 0}

iex> Predicator.Duration.new()
%{years: 0, months: 0, weeks: 0, days: 0, hours: 0, minutes: 0, seconds: 0, milliseconds: 0}

parse(string)

@spec parse(binary()) :: {:ok, Predicator.Types.duration()} | :error

Parses a duration literal string into a duration map.

This is the inverse of to_string/1: the whole string must be a sequence of one or more <digits><unit> pairs, with no whitespace, no sign, and no partial consumption. The accepted units are exactly the eight to_string/1 emits - y, mo, w, d, h, m, s, ms - with mo and ms matched before the single-character units so "1mo" is one month, not one minute followed by a stray o. Values are non-negative integers. Repeated units accumulate, matching add_unit/3. Anything else - a bad unit, trailing or leading junk, a sign, a bare number, or the empty string - is :error.

Examples

iex> Predicator.Duration.parse("3d8h30m")
{:ok, %{years: 0, months: 0, weeks: 0, days: 3, hours: 8, minutes: 30, seconds: 0, milliseconds: 0}}

iex> Predicator.Duration.parse("0s")
{:ok, %{years: 0, months: 0, weeks: 0, days: 0, hours: 0, minutes: 0, seconds: 0, milliseconds: 0}}

iex> Predicator.Duration.parse("1d ")
:error

subtract_from_date(date, duration)

@spec subtract_from_date(Date.t(), Predicator.Types.duration()) :: Date.t()

Subtracts a duration from a Date, returning a Date.

Examples

iex> date = ~D[2024-01-25]
iex> duration = Predicator.Duration.new(days: 3, weeks: 1)
iex> Predicator.Duration.subtract_from_date(date, duration)
~D[2024-01-15]

subtract_from_datetime(datetime, duration)

@spec subtract_from_datetime(DateTime.t(), Predicator.Types.duration()) ::
  DateTime.t()

Subtracts a duration from a DateTime, returning a DateTime.

Examples

iex> datetime = ~U[2024-01-17T14:00:00Z]
iex> duration = Predicator.Duration.new(days: 2, hours: 3, minutes: 30)
iex> Predicator.Duration.subtract_from_datetime(datetime, duration)
~U[2024-01-15T10:30:00Z]

to_milliseconds(duration)

@spec to_milliseconds(Predicator.Types.duration()) :: integer()

Converts a duration to total milliseconds (approximate for months and years).

Uses approximate conversions:

  • 1 month = 30 days
  • 1 year = 365 days

Examples

iex> Predicator.Duration.to_milliseconds(%{seconds: 1, milliseconds: 500})
1500

iex> Predicator.Duration.to_milliseconds(%{minutes: 1, seconds: 30, milliseconds: 250})
90250

to_seconds(duration)

@spec to_seconds(Predicator.Types.duration()) :: integer()

Converts a duration to total seconds (approximate for months and years).

Uses approximate conversions:

  • 1 month = 30 days
  • 1 year = 365 days

Examples

iex> Predicator.Duration.to_seconds(%{days: 1, hours: 2, minutes: 30, seconds: 15})
95415

iex> Predicator.Duration.to_seconds(%{weeks: 2})
1209600

to_string(duration)

@spec to_string(Predicator.Types.duration()) :: binary()

Converts a duration to a human-readable string.

Examples

iex> duration = Predicator.Duration.new(days: 3, hours: 8, minutes: 30)
iex> Predicator.Duration.to_string(duration)
"3d8h30m"

iex> duration = Predicator.Duration.new(weeks: 2)
iex> Predicator.Duration.to_string(duration)
"2w"