epochkit
slack timestamps reference

Slack date formatting: the <!date^...> syntax explained

A complete guide to Slack's <!date^UNIX^TOKEN|fallback> syntax: all 10 date and time tokens, fallback text rules, where it works, and worked examples.

Published · By epochkit
Share X
Table of contents

TL;DR: Slack date formatting uses the syntax <!date^UNIX_SECONDS^TOKEN_STRING|FALLBACK_TEXT>. Replace UNIX_SECONDS with a Unix timestamp in seconds, compose the token string from tokens like {date_short_pretty} and {time}, and always provide fallback text after the pipe. Slack renders the result in each viewer’s own timezone. The syntax works in app-published messages — API calls and incoming webhooks — not in messages typed by hand.


Why Slack date formatting exists

Slack date formatting is a message-markup feature that lets a single Unix timestamp render as a readable, viewer-local date inside a Slack message. When an app posts <!date^1784563200^{date_short_pretty} at {time}|Jul 20, 2026 at 4:00 PM UTC>, Slack reads the Unix value — seconds since January 1, 1970 UTC — and formats it for each reader individually. Per the official formatting documentation, the displayed time is based on the timezone setting of the device used to observe the text. A teammate in New York sees “Jul 20, 2026 at 12:00 PM”, a teammate in London sees “Jul 20, 2026 at 5:00 PM”, and a teammate in Tokyo sees the correct local time on July 21 — all from one message, with no timezone arithmetic by anyone. This solves the classic distributed-team problem where “the deploy starts at 4 PM” means a different clock reading for every reader.


The syntax, piece by piece

The full form, including the optional link component, is:

<!date^timestamp^token_string^optional_link|fallback_text>
  • < and > — wrap the entire command so Slack treats it as markup rather than plain text.
  • !date — tells Slack to parse the contents as a date command.
  • timestamp — a Unix timestamp in whole seconds (10 digits for current dates). A 13-digit value is milliseconds; divide by 1000 first.
  • token_string — a mix of plain text and formatting tokens. You can combine tokens freely: {date_short_pretty} at {time} is a valid token string, and so is Posted {ago}.
  • optional_link — an optional fully qualified URL. When present, Slack renders the formatted date as a link to that URL.
  • fallback_text — plain text shown when a client cannot process the date command. This part is separated by a pipe (|) and should always be included.

Full token reference

The documentation defines ten tokens. The table below uses 1784563200 (Monday, July 20, 2026 at 16:00 UTC) as the example value, rendered for a viewer in New York.

TokenExample outputNotes
{date_num}2026-07-20Numeric with leading zeros; the most developer-friendly form
{date}July 20th, 2026Omits the year when the date is within six months
{date_short}Jul 20, 2026Abbreviated month; omits the year when within six months
{date_long}Monday, July 20th, 2026Adds the weekday; omits the year when within six months
{date_pretty}today / July 20thLike {date}, but substitutes “yesterday”, “today”, or “tomorrow”
{date_short_pretty}today / Jul 20Like {date_short} with the same substitution
{date_long_pretty}today / Monday, July 20thLike {date_long} with the same substitution
{time}12:00 PMFollows the viewer’s 12-hour or 24-hour clock preference
{time_secs}12:00:00 PMSame as {time}, with seconds
{ago}3 minutes agoHuman-readable elapsed time

Smart tokens

The three _pretty variants are context-aware. When the timestamp falls on the current, previous, or next day in the viewer’s local timezone, Slack replaces the date with “today”, “yesterday”, or “tomorrow”. This makes announcements read naturally — “the incident review is today at 12:00 PM” — without the sender knowing when the message will be read. Use the plain {date} variants when you always want an explicit date, and {date_num} when you need a stable, sortable value for log lines or audit summaries.

12-hour vs 24-hour time

{time} and {time_secs} respect each viewer’s clock display preference. The same message renders as “6:39 PM” for a viewer using 12-hour time and “18:39” for a viewer using 24-hour time. You cannot force one style from the sender’s side — which is the point: the reader’s own settings win.


Fallback text rules

Fallback text is the plain-text portion after the pipe, displayed whenever a client cannot process the date command. The documentation recommends including timezone information in the fallback, because the reader’s timezone may differ from yours — a fallback that just says “4:00 PM” is ambiguous the moment it leaves your machine. A good fallback spells out the date, time, and zone explicitly:

<!date^1784563200^{date_short_pretty} at {time}|Jul 20, 2026 at 4:00 PM UTC>

If Slack cannot render the markup — in certain notification contexts or older clients — the reader still sees “Jul 20, 2026 at 4:00 PM UTC”, which is unambiguous everywhere. Treat the fallback as required, not optional: it is the only part of the message you fully control.


Where it works — and where it does not

Slack date formatting is an app-level feature. Per the documentation, the syntax works in app-published text across the messaging APIs, incoming webhooks, and interactive surfaces. In practice that means messages posted by bots and integrations — in channels, direct messages, and threads — render the markup correctly.

It does not work in messages typed by hand. If you paste <!date^...> into the Slack message composer as a human user, Slack treats it as literal text and your teammates see the raw markup. The syntax also renders literally in fields that only accept plain text. If you need viewer-local dates in a manual message, the practical options are posting through a webhook or workflow you control, or falling back to an explicit UTC time in text.


Worked examples

Each example below uses a real Unix timestamp. epochkit’s Slack timestamp generator builds these strings interactively, with a live preview and an auto-generated fallback.

Event announcement via incoming webhook

1784563200 is Monday, July 20, 2026 at 16:00 UTC.

{
  "text": "Maintenance window starts <!date^1784563200^{date_long_pretty} at {time}|Monday, July 20, 2026 at 4:00 PM UTC>."
}

Rendered for different viewers:

Viewer locationSees
New YorkMaintenance window starts Monday, July 20th at 12:00 PM.
LondonMaintenance window starts Monday, July 20th at 5:00 PM.
TokyoMaintenance window starts Tuesday, July 21st at 1:00 AM.

One timestamp, three correct local readings — including the date rollover for Tokyo, which plain text almost always gets wrong.

Deadline reminder with a smart token

1785763800 is Monday, August 3, 2026 at 13:30 UTC.

Reports are due <!date^1785763800^{date_short_pretty} at {time}|Aug 3, 2026 at 1:30 PM UTC>.

A New York reader sees “Aug 3, 2026 at 9:30 AM”; a London reader sees “Aug 3, 2026 at 2:30 PM”. Read on the day itself, both see “today at …” thanks to the _pretty token.

Elapsed time with {ago}

Deploy started <!date^1784563200^{ago}|Jul 20, 2026 16:00 UTC> — logs in #deploys.

The {ago} token renders as elapsed time such as “3 minutes ago” or “2 days ago”, which is useful for incident timelines and status updates where recency matters more than the absolute clock time.

Linked date

<!date^1784563200^{date_short} at {time}^https://example.com/status|Jul 20, 2026 at 4:00 PM UTC>

With the optional link component filled in, the rendered date becomes a clickable link to the URL — handy for pointing an announcement at a status page or calendar entry.


Troubleshooting

The raw <!date^...> markup shows literally. The message was typed by hand in the composer, or posted into a plain-text-only field. Date formatting only renders in app-published text — route the message through the API, a webhook, or a workflow instead.

Readers see the fallback text instead of a formatted date. The viewing surface could not process the date command. This is expected behavior, and it is exactly why the fallback should contain the full date, time, and timezone.

The rendered time is wrong by hours. The Unix timestamp was probably calculated in local time instead of UTC. A Unix timestamp is always UTC-based; verify the value with epochkit’s Unix converter before posting.

Slack rejects or mangles the timestamp. Check the digit count. JavaScript’s Date.now() returns milliseconds (13 digits); Slack expects seconds (10 digits). Use Math.floor(Date.now() / 1000).


Use epochkit’s Slack timestamp generator to pick a date, compose a token string from clickable token buttons or presets, and copy the complete <!date^...> syntax with a Slack-style preview. To get the Unix value itself, the Unix timestamp converter converts in both directions.

How we create this content: Our guides are drafted with the help of AI tools, then reviewed, fact-checked against the relevant specifications (POSIX, RFC 3339, crontab(5), or platform docs), and tested in epochkit's own tools by a human before publishing. We update them when specs or platform behavior change. Spotted something wrong? Email contact@epochkit.dev — we'll fix it.