# `Ash.Type.Duration`
[🔗](https://github.com/ash-project/ash/blob/v3.31.0/lib/ash/type/duration.ex#L5)

Represents a Duration

A builtin type that can be referenced via `:duration`

### Constraints

* `:units` - The units permitted to be non-zero; any unit outside the set must be zero, otherwise casting fails. Either an explicit list of units, or a shorthand for one side of the comparability boundary: `:year_month` (`[:year, :month]`) or `:day_time` (`[:week, :day, :hour, :minute, :second, :microsecond]`). Confining an attribute to a single side keeps its values comparable (see `Ash.Type.Duration.compare/2`).

# `compare`

```elixir
@spec compare(Duration.t(), Duration.t()) :: :lt | :eq | :gt
```

Compares two durations as a total order, matching how the AshPostgres data
layer (PostgreSQL `interval`) compares them: a fixed conversion of `month` → 30
days and `day` → 24 hours (so `year` → 360 days, `week` → 7 days), down to
microseconds.

`Duration` is only *partially* ordered in general — a month is not a fixed
number of days — which is why Elixir ships `Duration` without a `compare/2`, and
why data layers disagree on cross-unit comparison: PostgreSQL uses 30-day
months, Neo4j ~30.44-day months, and Elixir's `to_timeout/1` refuses `month`/
`year` outright. This adopts PostgreSQL's convention so in-memory comparison
stays aligned with the dominant data layer rather than raising or drifting.
Within the day/time units, or within the year/month units, the result is exact
and portable across those backends; only comparison *across* that boundary
depends on the 30-day convention.

Computed from the integer fields directly, so microsecond precision is kept
(unlike `to_timeout/1`, which truncates to milliseconds).

This function is the single place the convention lives; if Elixir core later
gains a `Duration.compare/2`, it can delegate here.

# `handle_change?`

# `prepare_change?`

---

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