# `Timex.Duration`
[🔗](https://github.com/bitwalker/timex/blob/4.0.0/lib/time/duration.ex#L1)

This module provides a friendly API for working with Erlang
timestamps, i.e. `{megasecs, secs, microsecs}`. In addition,
it provides an easy way to wrap the measurement of function
execution time (via `measure`).

# `measurement_units`

```elixir
@type measurement_units() ::
  :microseconds | :milliseconds | :seconds | :minutes | :hours
```

# `t`

```elixir
@type t() :: %Timex.Duration{
  megaseconds: integer(),
  microseconds: integer(),
  seconds: integer()
}
```

# `to_options`

```elixir
@type to_options() :: [{:truncate, boolean()}]
```

# `units`

```elixir
@type units() ::
  :microsecond
  | :microseconds
  | :millisecond
  | :milliseconds
  | :second
  | :seconds
  | :minutes
  | :hours
  | :days
  | :weeks
```

# `abs`

```elixir
@spec abs(t()) :: t()
```

Returns the absolute value of the provided Duration.

## Example

    iex> d = %Timex.Duration{megaseconds: -1, seconds: -2, microseconds: -3}
    ...> Timex.Duration.abs(d)
    %Timex.Duration{megaseconds: 1, seconds: 2, microseconds: 3}

# `add`

```elixir
@spec add(t(), t()) :: t()
```

Add one Duration to another.

## Examples

    iex> d = %Timex.Duration{megaseconds: 1, seconds: 1, microseconds: 1}
    ...> Timex.Duration.add(d, d)
    %Timex.Duration{megaseconds: 2, seconds: 2, microseconds: 2}

    iex> d = %Timex.Duration{megaseconds: 1, seconds: 750000, microseconds: 750000}
    ...> Timex.Duration.add(d, d)
    %Timex.Duration{megaseconds: 3, seconds: 500001, microseconds: 500000}

# `diff`

This function determines the difference in time between two timestamps
(represented by Duration structs). If the second timestamp is omitted,
`Duration.now` will be used as the reference timestamp. If the first
timestamp argument occurs before the second, the resulting measurement will
be a negative value.

The type argument is an atom indicating the units the measurement should be
returned in. If no type argument is provided, a Duration will be returned.

Valid measurement units for this function are:

    :microseconds, :milliseconds, :seconds, :minutes, :hours, :days, or :weeks

## Examples

    iex> alias Timex.Duration
    ...> d = Duration.from_erl({1457, 136000, 785000})
    ...> Duration.diff(d, Duration.zero, :days)
    16865

# `elapsed`

An alias for `diff/3`

# `epoch`

```elixir
@spec epoch() :: t()
```

Returns the duration since the first day of year 0 to Epoch.

## Example

    iex> Timex.Duration.epoch()
    %Timex.Duration{megaseconds: 62_167, seconds: 219_200, microseconds: 0}

# `epoch`

```elixir
@spec epoch(nil) :: t()
@spec epoch(units()) :: non_neg_integer()
```

Returns the amount of time since the first day of year 0 to Epoch.

The argument is an atom indicating the type of time units to return.

The allowed unit type atoms are:
- :microseconds
- :milliseconds
- :seconds
- :minutes
- :hours
- :days
- :weeks

## Examples

    iex> Timex.Duration.epoch(:seconds)
    62_167_219_200

If the specified type is nil, a duration since the first day of year 0 to Epoch
is returned.

    iex> Timex.Duration.epoch(nil)
    %Timex.Duration{megaseconds: 62_167, seconds: 219_200, microseconds: 0}

# `from_clock`

Converts a clock tuple, i.e. `{hour, minute, second, microsecond}` to a Duration.

## Example

    iex> Timex.Duration.from_clock({1, 2, 3, 4})
    %Timex.Duration{megaseconds: 0, seconds: 3723, microseconds: 4}

# `from_days`

```elixir
@spec from_days(integer() | float()) :: t()
```

Converts an integer value representing days to a Duration

# `from_erl`

```elixir
@spec from_erl(Timex.Types.timestamp()) :: t()
```

Converts an Erlang timestamp to a Duration

## Example

    iex> Timex.Duration.from_erl({1, 2, 3})
    %Timex.Duration{megaseconds: 1, seconds: 2, microseconds: 3}

# `from_hours`

```elixir
@spec from_hours(integer() | float()) :: t()
```

Converts an integer value representing hours to a Duration

# `from_microseconds`

```elixir
@spec from_microseconds(integer()) :: t()
```

Converts an integer value representing microseconds to a Duration

# `from_milliseconds`

```elixir
@spec from_milliseconds(integer() | float()) :: t()
```

Converts an integer value representing milliseconds to a Duration

# `from_minutes`

```elixir
@spec from_minutes(integer() | float()) :: t()
```

Converts an integer value representing minutes to a Duration

# `from_seconds`

```elixir
@spec from_seconds(integer() | float()) :: t()
```

Converts an integer value representing seconds to a Duration

# `from_time`

```elixir
@spec from_time(Time.t()) :: t()
```

Converts a Time to a Duration

## Example

    iex> Timex.Duration.from_time(~T[01:01:30])
    %Timex.Duration{megaseconds: 0, seconds: 3690, microseconds: 0}

# `from_weeks`

```elixir
@spec from_weeks(integer() | float()) :: t()
```

Converts an integer value representing weeks to a Duration

# `invert`

```elixir
@spec invert(t()) :: t()
```

Invert a Duration, i.e. a positive duration becomes a negative one, and vice versa

## Example

    iex> d = %Timex.Duration{megaseconds: -1, seconds: -2, microseconds: -3}
    ...> Timex.Duration.invert(d)
    %Timex.Duration{megaseconds: 1, seconds: 2, microseconds: 3}

# `measure`

```elixir
@spec measure((-&gt; any())) :: {t(), any()}
```

Evaluates fun() and measures the elapsed time.

Returns `{Duration.t, result}`.

## Example

    iex> {_timestamp, result} = Duration.measure(fn -> 2 * 2 end)
    ...> result == 4
    true

# `measure`

```elixir
@spec measure(fun(), [any()]) :: {t(), any()}
```

Evaluates `apply(fun, args)`, and measures execution time.

Returns `{Duration.t, result}`.

## Example

    iex> {_timestamp, result} = Duration.measure(fn x, y -> x * y end, [2, 4])
    ...> result == 8
    true

# `measure`

```elixir
@spec measure(module(), atom(), [any()]) :: {t(), any()}
```

Evaluates `apply(module, fun, args)`, and measures execution time.

Returns `{Duration.t, result}`.

## Example

    iex> {_timestamp, result} = Duration.measure(Enum, :map, [[1,2], &(&1*2)])
    ...> result == [2, 4]
    true

# `normalize`

# `now`

```elixir
@spec now(nil) :: t()
@spec now(units()) :: non_neg_integer()
```

Returns the amount of time since Epoch.

The argument is an atom indicating the type of time units to return.

The allowed unit type atoms are:
- :microsecond(s)
- :millisecond(s)
- :second(s)
- :minutes
- :hours
- :days
- :weeks

When a unit is specified, the result is an integer count of whole units since Epoch.

## Examples

    iex> Timex.Duration.now(:seconds)
    1483141644

When the argument is omitted or nil, a Duration is returned.

    iex> Timex.Duration.now
    %Timex.Duration{megaseconds: 1483, seconds: 141562, microseconds: 536938}

# `parse`

```elixir
@spec parse(String.t()) :: {:ok, t()} | {:error, term()}
```

Parses a duration string (in ISO-8601 format) into a Duration struct.

# `parse`

```elixir
@spec parse(String.t(), module()) :: {:ok, t()} | {:error, term()}
```

Parses a duration string into a Duration struct, using the provided parser module.

# `parse!`

```elixir
@spec parse!(String.t()) :: t() | no_return()
```

Same as parse/1, but returns the Duration unwrapped, and raises on error

# `parse!`

```elixir
@spec parse!(String.t(), module()) :: t() | no_return()
```

Same as parse/2, but returns the Duration unwrapped, and raises on error

# `scale`

```elixir
@spec scale(t(), coefficient :: integer() | float()) :: t()
```

Scale a Duration by some coefficient value, i.e. a scale of 2 is twice is long.

## Example

    iex> d = %Timex.Duration{megaseconds: 1, seconds: 1, microseconds: 1}
    ...> Timex.Duration.scale(d, 2)
    %Timex.Duration{megaseconds: 2, seconds: 2, microseconds: 2}

# `sub`

```elixir
@spec sub(t(), t()) :: t()
```

Subtract one Duration from another.

## Example

    iex> d1 = %Timex.Duration{megaseconds: 3, seconds: 3, microseconds: 3}
    ...> d2 = %Timex.Duration{megaseconds: 2, seconds: 2, microseconds: 2}
    ...> Timex.Duration.sub(d1, d2)
    %Timex.Duration{megaseconds: 1, seconds: 1, microseconds: 1}

# `to_clock`

Converts a Duration to a clock tuple, i.e. `{hour,minute,second,microsecond}`.

## Example

    iex> d = %Timex.Duration{megaseconds: 1, seconds: 1, microseconds: 50}
    ...> Timex.Duration.to_clock(d)
    {277, 46, 41, 50}

# `to_days`

```elixir
@spec to_days(t()) :: float()
```

Converts a Duration to its value in days

## Example

    iex> Duration.to_days(Duration.from_hours(6))
    0.25
    iex> Duration.to_days(Duration.from_hours(25), truncate: true)
    1

# `to_days`

```elixir
@spec to_days(t(), to_options()) :: float() | integer()
@spec to_days(integer() | float(), :microseconds) :: float()
@spec to_days(integer() | float(), :milliseconds) :: float()
@spec to_days(integer() | float(), :seconds) :: float()
@spec to_days(integer() | float(), :minutes) :: float()
@spec to_days(integer() | float(), :hours) :: float()
@spec to_days(integer() | float(), :days) :: float()
@spec to_days(integer() | float(), :weeks) :: float()
```

# `to_erl`

```elixir
@spec to_erl(t()) :: Timex.Types.timestamp()
```

Converts a Duration to an Erlang timestamp

## Example

    iex> d = %Timex.Duration{megaseconds: 1, seconds: 2, microseconds: 3}
    ...> Timex.Duration.to_erl(d)
    {1, 2, 3}

# `to_hours`

```elixir
@spec to_hours(t()) :: float()
```

Converts a Duration to its value in hours

## Example

    iex> Duration.to_hours(Duration.from_minutes(105))
    1.75
    iex> Duration.to_hours(Duration.from_minutes(105), truncate: true)
    1

# `to_hours`

```elixir
@spec to_hours(t(), to_options()) :: float() | integer()
@spec to_hours(integer() | float(), :microseconds) :: float()
@spec to_hours(integer() | float(), :milliseconds) :: float()
@spec to_hours(integer() | float(), :seconds) :: float()
@spec to_hours(integer() | float(), :minutes) :: float()
@spec to_hours(integer() | float(), :hours) :: float()
@spec to_hours(integer() | float(), :days) :: float()
@spec to_hours(integer() | float(), :weeks) :: float()
```

# `to_microseconds`

```elixir
@spec to_microseconds(t()) :: integer()
```

Converts a Duration to its value in microseconds

## Example

    iex> Duration.to_microseconds(Duration.from_milliseconds(10.5))
    10_500

# `to_microseconds`

```elixir
@spec to_microseconds(t(), to_options()) :: integer()
@spec to_microseconds(integer() | float(), :microseconds) :: float()
@spec to_microseconds(integer() | float(), :milliseconds) :: float()
@spec to_microseconds(integer() | float(), :seconds) :: float()
@spec to_microseconds(integer() | float(), :minutes) :: float()
@spec to_microseconds(integer() | float(), :hours) :: float()
@spec to_microseconds(integer() | float(), :days) :: float()
@spec to_microseconds(integer() | float(), :weeks) :: float()
```

# `to_milliseconds`

```elixir
@spec to_milliseconds(t()) :: float()
```

Converts a Duration to its value in milliseconds

## Example

    iex> Duration.to_milliseconds(Duration.from_seconds(1))
    1000.0
    iex> Duration.to_milliseconds(Duration.from_seconds(1.543))
    1543.0
    iex> Duration.to_milliseconds(Duration.from_seconds(1.543), truncate: true)
    1543

# `to_milliseconds`

```elixir
@spec to_milliseconds(t(), to_options()) :: float() | integer()
@spec to_milliseconds(integer() | float(), :microseconds) :: float()
@spec to_milliseconds(integer() | float(), :milliseconds) :: float()
@spec to_milliseconds(integer() | float(), :seconds) :: float()
@spec to_milliseconds(integer() | float(), :minutes) :: float()
@spec to_milliseconds(integer() | float(), :hours) :: float()
@spec to_milliseconds(integer() | float(), :days) :: float()
@spec to_milliseconds(integer() | float(), :weeks) :: float()
```

# `to_minutes`

```elixir
@spec to_minutes(t()) :: float()
```

Converts a Duration to its value in minutes

## Example

    iex> Duration.to_minutes(Duration.from_seconds(90))
    1.5
    iex> Duration.to_minutes(Duration.from_seconds(65), truncate: true)
    1

# `to_minutes`

```elixir
@spec to_minutes(t(), to_options()) :: float() | integer()
@spec to_minutes(integer() | float(), :microseconds) :: float()
@spec to_minutes(integer() | float(), :milliseconds) :: float()
@spec to_minutes(integer() | float(), :seconds) :: float()
@spec to_minutes(integer() | float(), :minutes) :: float()
@spec to_minutes(integer() | float(), :hours) :: float()
@spec to_minutes(integer() | float(), :days) :: float()
@spec to_minutes(integer() | float(), :weeks) :: float()
```

# `to_seconds`

```elixir
@spec to_seconds(t()) :: float()
```

Converts a Duration to its value in seconds

## Example

    iex> Duration.to_seconds(Duration.from_milliseconds(1500))
    1.5
    iex> Duration.to_seconds(Duration.from_milliseconds(1500), truncate: true)
    1

# `to_seconds`

```elixir
@spec to_seconds(t(), to_options()) :: float() | integer()
@spec to_seconds(integer() | float(), :microseconds) :: float()
@spec to_seconds(integer() | float(), :milliseconds) :: float()
@spec to_seconds(integer() | float(), :seconds) :: float()
@spec to_seconds(integer() | float(), :minutes) :: float()
@spec to_seconds(integer() | float(), :hours) :: float()
@spec to_seconds(integer() | float(), :days) :: float()
@spec to_seconds(integer() | float(), :weeks) :: float()
```

# `to_string`

```elixir
@spec to_string(t()) :: String.t()
```

Converts a Duration to a string, using the ISO standard for formatting durations.

## Examples

    iex> d = %Timex.Duration{megaseconds: 0, seconds: 3661, microseconds: 0}
    ...> Timex.Duration.to_string(d)
    "PT1H1M1S"

    iex> d = %Timex.Duration{megaseconds: 102, seconds: 656013, microseconds: 33}
    ...> Timex.Duration.to_string(d)
    "P3Y3M3DT3H33M33.000033S"

# `to_time`

```elixir
@spec to_time(t()) :: {:ok, Time.t()} | {:error, atom()}
```

Converts a Duration to a Time if the duration fits within a 24-hour clock.
If it does not, an error tuple is returned.

## Examples

    iex> d = %Timex.Duration{megaseconds: 0, seconds: 4000, microseconds: 0}
    ...> Timex.Duration.to_time(d)
    {:ok, ~T[01:06:40]}

    iex> d = %Timex.Duration{megaseconds: 1, seconds: 0, microseconds: 0}
    ...> Timex.Duration.to_time(d)
    {:error, :invalid_time}

# `to_time!`

```elixir
@spec to_time!(t()) :: Time.t() | no_return()
```

Same as to_time/1, but returns the Time directly. Raises an error if the
duration does not fit within a 24-hour clock.

## Examples

    iex> d = %Timex.Duration{megaseconds: 0, seconds: 4000, microseconds: 0}
    ...> Timex.Duration.to_time!(d)
    ~T[01:06:40]

    iex> d = %Timex.Duration{megaseconds: 1, seconds: 0, microseconds: 0}
    ...> Timex.Duration.to_time!(d)
    ** (ArgumentError) cannot convert {277, 46, 40} to time, reason: :invalid_time

# `to_weeks`

```elixir
@spec to_weeks(t()) :: float()
```

Converts a Duration to its value in weeks

## Example

    iex> Duration.to_weeks(Duration.from_days(14))
    2.0
    iex> Duration.to_weeks(Duration.from_days(13), truncate: true)
    1

# `to_weeks`

```elixir
@spec to_weeks(t(), to_options()) :: float() | integer()
@spec to_weeks(integer() | float(), :microseconds) :: float()
@spec to_weeks(integer() | float(), :milliseconds) :: float()
@spec to_weeks(integer() | float(), :seconds) :: float()
@spec to_weeks(integer() | float(), :minutes) :: float()
@spec to_weeks(integer() | float(), :hours) :: float()
@spec to_weeks(integer() | float(), :days) :: float()
@spec to_weeks(integer() | float(), :weeks) :: float()
```

# `zero`

```elixir
@spec zero() :: t()
```

Return a timestamp representing a time lapse of length 0.

    iex> Timex.Duration.zero |> Timex.Duration.to_seconds
    0.0

Can be useful for operations on collections of durations. For instance,

    Enum.reduce(durations, Duration.zero, &Duration.add(&1, &2))

Can also be used to represent the timestamp of the start of the UNIX epoch,
as all Erlang timestamps are relative to this point.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
