> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mira.party/llms.txt
> Use this file to discover all available pages before exploring further.

# Timestamps & durations

> Every way to format a date, a time, or a length of time inside a script.

Anywhere a script knows about a moment in time (`{user.joined_at}`, `{expiration}`,
`{nuke.next}`) or a length of time (`{duration}`, `{nuke.interval}`), you get the
**same full set of suffixes**. Learn it once and it works everywhere.

<Info>
  Nothing here is opt-in. If a variable is a date or a duration, every suffix on
  this page works on it — including ones added to the bot after you read this.
</Info>

## Dates and times

The bare variable is a **raw Unix timestamp** — a plain number like `1618935600`.
That's deliberate: it's the one form you can build anything else out of.

```javascript theme={null}
{description: joined <t:{user.joined_at}:R>}
```

### Let Discord do it

Discord renders `<t:NUMBER:STYLE>` in everyone's own timezone and language. Drop
the bare variable in and pick a style letter:

| Markup                   | Renders as                   |
| ------------------------ | ---------------------------- |
| `<t:{user.joined_at}:R>` | 3 years ago                  |
| `<t:{user.joined_at}:t>` | 16:20                        |
| `<t:{user.joined_at}:T>` | 16:20:00                     |
| `<t:{user.joined_at}:d>` | 20/04/2021                   |
| `<t:{user.joined_at}:D>` | 20 April 2021                |
| `<t:{user.joined_at}:f>` | 20 April 2021 16:20          |
| `<t:{user.joined_at}:F>` | Tuesday, 20 April 2021 16:20 |

### Or use a named suffix

Every style above also has a name, so you don't have to remember the letters:

| Suffix                       | Same as | Renders as                   |
| ---------------------------- | ------- | ---------------------------- |
| `{user.joined_at}`           | —       | `1618935600`                 |
| `{user.joined_at.unix}`      | —       | `1618935600`                 |
| `{user.joined_at.timestamp}` | —       | `1618935600`                 |
| `{user.joined_at.relative}`  | `:R`    | 3 years ago                  |
| `{user.joined_at.shorttime}` | `:t`    | 16:20                        |
| `{user.joined_at.time}`      | `:T`    | 16:20:00                     |
| `{user.joined_at.shortdate}` | `:d`    | 20/04/2021                   |
| `{user.joined_at.date}`      | `:D`    | 20 April 2021                |
| `{user.joined_at.short}`     | `:f`    | 20 April 2021 16:20          |
| `{user.joined_at.long}`      | `:F`    | Tuesday, 20 April 2021 16:20 |
| `{user.joined_at.iso}`       | —       | `2021-04-20T16:20:00+00:00`  |

<Tip>
  Use the named suffix when you just want a date on screen. Use the bare number
  with `<t:…:X>` when you're mixing several styles in one line, or when you want
  a style Discord supports that hasn't been given a name.
</Tip>

### Raw parts

For arithmetic or odd formats, the individual components are there too:

```javascript theme={null}
{content: born in {user.created_at.year}, month {user.created_at.month}}
```

`.year` `.month` `.day` `.hour` `.minute` `.second` `.microsecond`

## Durations

A length of time — how long a mute lasts, how often a channel is nuked. The bare
variable is the **long, readable form**:

| Suffix               | Renders as |
| -------------------- | ---------- |
| `{duration}`         | 2 hours    |
| `{duration.long}`    | 2 hours    |
| `{duration.short}`   | 2h         |
| `{duration.seconds}` | `7200`     |
| `{duration.minutes}` | `120`      |
| `{duration.hours}`   | `2`        |
| `{duration.days}`    | `0`        |

```javascript theme={null}
{content: muted for {duration.short} — back <t:{expiration}:R>}
```

> muted for 2h — back in 2 hours

The numeric suffixes are whole numbers, rounded down, counting the **total** in
that unit — a 90 minute duration is `90` minutes and `1` hour, not `1` hour and
`30` minutes. Combine with [operators](/scripting/operators) when you want the
number formatted: `{duration.seconds|comma}`.

## Where they show up

Some of the more useful ones. Each module's own `variables` subcommand lists the
rest.

<AccordionGroup>
  <Accordion title="Anything with a member or server" icon="user">
    | Variable             | What                         |
    | -------------------- | ---------------------------- |
    | `{user.created_at}`  | When their account was made  |
    | `{user.joined_at}`   | When they joined this server |
    | `{guild.created_at}` | When the server was made     |

    ```javascript theme={null}
    !welcome add #general {content: welcome {user.mention}, account made {user.created_at.relative}}
    ```
  </Accordion>

  <Accordion title="Moderation messages" icon="gavel">
    Available in [invoke messages](/moderation/cases#custom-responses), invoke DMs, and
    the jail message.

    | Variable                        | What                                                          |
    | ------------------------------- | ------------------------------------------------------------- |
    | `{duration}`                    | How long the punishment lasts — `Permanent` if there's no end |
    | `{expiration}` / `{expires_at}` | When it lifts — `Never` if permanent                          |

    ```javascript theme={null}
    !invoke mute {content: {user.mention} muted for {duration.short}, back {expiration.relative}}
    ```
  </Accordion>

  <Accordion title="Scheduled nukes" icon="bomb">
    | Variable          | What                           |
    | ----------------- | ------------------------------ |
    | `{nuke.interval}` | How often the channel is wiped |
    | `{nuke.next}`     | The next wipe                  |
    | `{nuke.last}`     | The wipe that just happened    |

    ```javascript theme={null}
    !nuke message #daily-chat {content: wiped. next one <t:{nuke.next}:R>}
    ```

    See [scheduled nukes](/moderation/channels#scheduled-nukes).
  </Accordion>

  <Accordion title="Bump reminders" icon="bell">
    | Variable                                      | What                                |
    | --------------------------------------------- | ----------------------------------- |
    | `{timestamp}` / `{next_bump}` / `{bump.next}` | When the server can be bumped again |

    ```javascript theme={null}
    !bumpreminder message {content: bump the server — next one <t:{timestamp}:R>}
    ```
  </Accordion>
</AccordionGroup>

## Gotchas

<AccordionGroup>
  <Accordion title="My timestamp shows a big number" icon="hashtag">
    You used the bare variable on its own. That's the raw Unix value — wrap it:
    `<t:{expiration}:R>`, or switch to a named suffix: `{expiration.relative}`.
  </Accordion>

  <Accordion title="It renders as literal braces" icon="brackets-curly">
    That variable doesn't exist in this context. Suffixes only work on something
    that's already a date or duration — `{user.name.relative}` is meaningless, and
    so is a variable the module never provides. Check the module's `variables`
    subcommand.
  </Accordion>

  <Accordion title="A permanent punishment prints Never" icon="infinity">
    Intentional. `{duration}` is `Permanent` and `{expiration}` is `Never` when
    there's no end date, and every suffix gives the same word, so
    `<t:{expiration}:R>` would render `<t:Never:R>`. Branch on it instead:

    ```javascript theme={null}
    {if: {duration}==Permanent && this one's permanent && back {expiration.relative}}
    ```
  </Accordion>

  <Accordion title="Times are in the wrong timezone" icon="globe">
    They aren't — Discord renders `<t:…>` in each viewer's own timezone, so the
    same message reads correctly for everyone. `.iso` is the exception: it's
    always UTC.
  </Accordion>
</AccordionGroup>
