ULID ↔ timestamp converter

Extract the millisecond timestamp from any ULID, or generate min/max ULIDs from a date to run range queries over lexicographically sorted keys — all in your browser.

epoch timestamp shortcuts

ULID → timestamp

date / timestamp → ULID

Only the first 10 characters of a ULID encode time (milliseconds, UTC). Use min as an inclusive lower bound and max as an inclusive upper bound for key range queries — ULIDs sort correctly as plain strings.

How a ULID encodes time

A ULID is a 128-bit identifier written as 26 characters of Crockford base32 — an alphabet that drops I, L, O and U to avoid lookalikes and profanity. The first 10 characters are a 48-bit big-endian count of milliseconds since the Unix epoch (00:00:00 UTC, 1 January 1970); the remaining 16 characters are 80 bits of randomness that keep ULIDs created in the same millisecond unique. Because the timestamp occupies the most significant bits and base32 preserves numeric order, ULIDs sort by creation time as plain strings — the property that makes them popular as primary keys in Postgres, SQLite and DynamoDB, where insert order then matches key order. Precision is one millisecond, and 48 bits reach the year 10889. Decoding is case-insensitive.

Querying ULID keys by date

Because a ULID's prefix is its timestamp, you can filter rows by creation date without a separate created_at column. Generate the min ULID (timestamp + 16 zeros) for the start of your range and the max ULID (timestamp + 16 Zs) for the end, then query WHERE id BETWEEN '<min>' AND '<max>' — both bounds inclusive, in any store that compares keys as strings or bytes. The same pair works as DynamoDB sort-key conditions.