# `Lotus.Dashboards.DateToken`
[🔗](https://github.com/elixir-lotus/lotus/blob/v1.1.0/lib/lotus/dashboards/date_token.ex#L1)

Resolves relative date tokens in dashboard filter values.

A dashboard filter value, the `default_value` of a filter or a value in
`:filter_values`, can be a token such as `"last_30_days"` in place of a
concrete date. `Lotus.Dashboards` resolves the token each time a card runs,
so a dashboard shows current data without stored dates.

## Tokens

The ranges below are for a run on Monday 2026-09-14.

| Token | Range |
|-------|-------|
| `"today"` | 2026-09-14 to 2026-09-14 |
| `"yesterday"` | 2026-09-13 to 2026-09-13 |
| `"last_7_days"` | 2026-09-08 to 2026-09-14 |
| `"last_30_days"` | 2026-08-16 to 2026-09-14 |
| `"last_90_days"` | 2026-06-17 to 2026-09-14 |
| `"this_week"` | 2026-09-14 to 2026-09-20 |
| `"this_month"` | 2026-09-01 to 2026-09-30 |
| `"this_quarter"` | 2026-07-01 to 2026-09-30 |
| `"this_year"` | 2026-01-01 to 2026-12-31 |
| `"last_week"` | 2026-09-07 to 2026-09-13 |
| `"last_month"` | 2026-08-01 to 2026-08-31 |
| `"last_quarter"` | 2026-04-01 to 2026-06-30 |
| `"last_year"` | 2025-01-01 to 2025-12-31 |

The `last_N_days` tokens include today. The week, month, quarter and year
tokens cover the full calendar period, also the days after today. Weeks are
ISO weeks and start on Monday. Today is `Date.utc_today/0` unless the caller
gives a date.

## Resolution by filter type

- `:date_range` - every token becomes `"YYYY-MM-DD,YYYY-MM-DD"`, the value
  that the `date_range_start` and `date_range_end` transforms split
- `:date` - `"today"` and `"yesterday"` become `"YYYY-MM-DD"`. A range token
  stays unchanged, and `Lotus.Storage.DashboardFilter` does not accept one as
  the `default_value`
- `:text`, `:number` and `:select` - the value stays unchanged

A value that is not a token, a concrete date for example, stays unchanged.

# `filter_type`

```elixir
@type filter_type() :: :text | :number | :date | :date_range | :select
```

# `token`

```elixir
@type token() :: String.t()
```

# `range`

```elixir
@spec range(term(), Date.t()) :: {:ok, Date.Range.t()} | :error
```

Returns the date range of `token` relative to `today`.

Returns `:error` when `token` is not a token.

## Examples

    iex> Lotus.Dashboards.DateToken.range("last_quarter", ~D[2026-09-14])
    {:ok, Date.range(~D[2026-04-01], ~D[2026-06-30])}

    iex> Lotus.Dashboards.DateToken.range("2026-09-14", ~D[2026-09-14])
    :error

# `resolve`

```elixir
@spec resolve(term(), filter_type(), Date.t()) :: term()
```

Resolves `value` for a filter of `filter_type` relative to `today`.

See the "Resolution by filter type" section of this module for the rules.

## Examples

    iex> Lotus.Dashboards.DateToken.resolve("last_7_days", :date_range, ~D[2026-09-14])
    "2026-09-08,2026-09-14"

    iex> Lotus.Dashboards.DateToken.resolve("today", :date, ~D[2026-09-14])
    "2026-09-14"

    iex> Lotus.Dashboards.DateToken.resolve("today", :text, ~D[2026-09-14])
    "today"

# `single_day?`

```elixir
@spec single_day?(term()) :: boolean()
```

Returns `true` when `value` is a token for one day, `"today"` or
`"yesterday"`.

## Examples

    iex> Lotus.Dashboards.DateToken.single_day?("yesterday")
    true

    iex> Lotus.Dashboards.DateToken.single_day?("last_7_days")
    false

# `tokens`

```elixir
@spec tokens() :: [token()]
```

Returns all tokens.

## Examples

    iex> "last_30_days" in Lotus.Dashboards.DateToken.tokens()
    true

---

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