What actually shipped
This sits alongside the tool's existing mini-tools — the snowflake ID decoder, the date-range generator, and the duration calculator — as one more card in the same panel. If you've used any of those before, the layout will look immediately familiar: an input field, a format dropdown, and a result box that fills in once you run it.
How the extractor reads a UUIDv7 or ULID
UUIDv7 stores its 48-bit millisecond Unix timestamp in the first 48 bits of the identifier (roughly the first three hyphen-separated groups once the version nibble is accounted for). ULID takes a different approach: it Crockford-base32-encodes the same kind of millisecond timestamp into the leading 10 characters of a 26-character string, using an alphabet that deliberately excludes visually ambiguous characters like I, L, O, and U.
Because the two encodings look so different — one is grouped hex with hyphens, the other is a flat base32 string — the auto-detect logic doesn't need anything fancy: enough valid hex characters in the expected grouping means UUIDv7, otherwise it falls back to treating the string as a ULID. If the input doesn't cleanly parse as either, the tool reports that rather than guessing at a wrong date.
018f4c2e-1a2b-7c3d-8e4f-5a6b7c8d9e0f — 36 characters, hyphenated, hex digits, with a 7 as the first character of the third group. ULID looks like 01HN8X6ZKQ5J8VXENJ9M6XQZ3F — 26 characters, uppercase Crockford base32, no hyphens.Worked examples
Both examples below are illustrative sample identifiers, not values pulled from a real system — swap in your own ID and confirm the decoded date matches your expectation before relying on it for anything important.
| Input | Detected format | Decoded timestamp (illustrative) |
|---|---|---|
| 018f4c2e-1a2b-7c3d-8e4f-5a6b7c8d9e0f | UUIDv7 | ~2024-02, ms epoch from first 48 bits |
| 01HN8X6ZKQ5J8VXENJ9M6XQZ3F | ULID | decoded from leading 10 base32 chars |
In each case, the extractor reads only the timestamp portion of the identifier — it doesn't (and can't) tell you anything about the random or sequence bits that make the rest of the ID unique. That's expected: those bits exist specifically so that two records created in the same millisecond still get distinct IDs, and there's no "date" hiding in them to extract.
Where this is actually useful
created_at column — because, by design, the ID already encodes that answer.Say (hypothetically) a support ticket references a record by its ULID primary key, and there's no timestamp column exposed in the tool you're looking at it through. Rather than tracing back to the database to find a created-at value, you can paste the ID straight into the extractor and read the creation date directly — that's the entire point of choosing a time-sortable ID format in the first place.
It's also handy for a quick sanity check during development: if you're generating UUIDv7 or ULID values in a new service and want to confirm the timestamp portion looks right (not, say, accidentally seconds instead of milliseconds, or a clock that's wildly off), pasting a freshly generated ID into the extractor is faster than writing a throwaway decoding script.
- Recovering a rough creation date from a UUIDv7 or ULID primary key with no separate timestamp column.
- Sanity-checking a new ID-generation library or service during development.
- Comparing the embedded timestamp against the expected auto-detected format when you're not sure which one you have.
Decode the embedded creation date from a UUIDv7 or ULID identifier — plus the existing epoch converter, snowflake decoder, and more, all running in your browser.
Try the free Unix Timestamp Converter →