ULID Generator — Ruby source
Generate Universally Unique Lexicographically Sortable Identifiers (ULID) - 26-character Crockford-base32 strings that sort by millisecond timestamp. Paste any ULID to decode its timestamp and randomness. Runs entirely in your browser.
This is the Ruby implementation — the same logic the interactive tool runs, in a shareable, citable form.
# ulid-generator - 26-char Crockford-base32 sortable ID: 10 chars of 48-bit ms timestamp + 16 chars of 80-bit randomness. Language: Ruby (3.1+, stdlib only). Port of src/lib/ulid.ts (Go twin: cli/ulid-generator) - encode/generate/decode-time core; inspectUlid (date/random-hex view) lives in this dir's javascript.js (80-line budget).
module Ulid
CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ' # no I, L, O, U
DECODE = CROCKFORD.chars.each_with_index.to_h { |c, i| [c, i] }.freeze
module_function
# Base32-encode the 128-bit big-endian value [time (48 bits) << 80 | random]
# into the canonical 26 chars. Ruby Integers are arbitrary precision, so the
# whole-value path replaces the byte-array long division of the other ports.
# Because 32**16 == 2**80, the first 10 chars equal the TS/Go twins' separate
# time encoding - the cross-language lock-step anchor.
def encode(time_ms, random_bytes)
value = ((time_ms & 0xFFFFFFFFFFFF) << 80) |
random_bytes.bytes.reduce(0) { |acc, b| (acc << 8) | b }
(+'').tap do |out|
26.times do
out.prepend(CROCKFORD[value & 31])
value >>= 5
end
end
end
# New ULID for the epoch-ms; Random.bytes is Ruby's CSPRNG, the analogue of
# Go's crypto/rand.
def generate(time_ms)
encode(time_ms, Random.bytes(10))
end
# Extract the 48-bit ms timestamp from the first 10 chars; raises on
# malformed input (wrong length, or a char outside the alphabet such as I/L/O/U).
def decode_time(ulid)
raise ArgumentError, "ulid: malformed id: length #{ulid.length}, want 26" unless ulid.length == 26
ulid[0, 10].each_char.reduce(0) do |ts, ch|
v = DECODE[ch]
raise ArgumentError, "ulid: invalid character #{ch.inspect}" unless v
ts * 32 + v
end
end
end
ulid = Ulid.generate(1_722_000_000_000)
puts "ulid: #{ulid}"
puts "time(ms): #{Ulid.decode_time(ulid)} (round-trip ok)"
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →