Discord & Slack timestamp decoder

Every Discord snowflake ID carries its creation time in its top 42 bits, and every Discord timestamp tag is just Unix epoch seconds with a display style attached. Decode a discord timestamp from a snowflake or a <t:…> tag, generate new tags for your own messages, or decode a slack epoch ts value — all client-side.

What is inside a Discord snowflake?

A Discord snowflake is a 64-bit unsigned integer, usually seen as a 17-to-19-digit string. Since Discord's launch it has packed a millisecond timestamp into its high bits alongside the identifiers needed to generate ids without collisions across many processes at once:

Bits Meaning
63–22 Milliseconds since the Discord epoch, 2015-01-01T00:00:00.000Z
21–17 Internal worker ID
16–12 Internal process ID
11–0 Counter, incremented for every ID generated on that process

To decode a discord timestamp from the ID by hand, right-shift the integer by 22 bits and add 1420070400000 — the Discord epoch in Unix milliseconds. It is the same layout Twitter's original Snowflake service popularized, just with a different epoch, so if you have decoded a Twitter or Instagram ID before, the algorithm is familiar. It is also the same idea as the creation time packed into a MongoDB ObjectId, which leads with four bytes of epoch seconds rather than 42 bits of milliseconds.

Discord's <t:…> timestamp tags

Outside of IDs, Discord also renders a Markdown-like tag — <t:UNIX:STYLE> — as a live, timezone-aware timestamp inside any message or bot embed. UNIX is plain epoch seconds; STYLE is one letter picking the format, from a short time like 4:20 PM to a relative phrase like 2 months ago that keeps updating for as long as the reader has the message open. The generator above builds all seven styles from a date you pick and previews how each one will render. Tagging "right now" instead of a fixed date? Grab the current Unix timestamp in seconds and drop it straight into the tag.

Slack's ts field and the slack epoch

Slack timestamps a message with its ts field: a string like 1629992397.000200. The slack epoch is ordinary Unix epoch seconds — the digits before the decimal point — so decoding is the same arithmetic as any other Unix timestamp. The six digits after the point are not sub-second precision; they are a sequence number Slack appends so that two messages landing in the same second still get distinct, sortable ids. That same value doubles as the message's unique identifier and, on a reply, as its thread_ts. Since a snowflake decodes to milliseconds and a Slack ts to seconds, it is worth checking which unit a bare number is before feeding it to anything that assumes one or the other.

Frequently asked questions

What is a Discord snowflake ID?

The unique 64-bit integer Discord assigns to every user, message, channel, server, and role. Its top 42 bits are a millisecond timestamp from the Discord epoch, so the creation time decodes straight out of the ID with no API call.

How do I decode a Discord timestamp tag like <t:1629992397:R>?

The number is Unix seconds; the trailing letter picks the style — t/T for short/long time, d/D for short/long date, f/F for short/long date-time, and R for a self-updating relative time. Discord renders it in each reader's own local timezone.

What epoch does Slack use for message timestamps?

Standard Unix epoch seconds, formatted as seconds.sequence — for example 1629992397.000200. The sequence digits disambiguate same-second messages; they are not additional time precision.

Why do two Discord snowflakes from the same millisecond differ?

Below the timestamp bits, a snowflake carries a worker ID, a process ID, and a per-process counter. IDs minted in the same millisecond differ only in those low bits — the decoded timestamp is identical, and that is expected, not a bug.