Time-based Universally Unique Identifiers (UUIDs v7) for NodeJS and the browser.
0
uuid7.js
edited
1const re = /^([0-9a-f]{8})-([0-9a-f]{4})-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
2
3/**
4 * Convert a byte array to an hexadecimal string.
5 */
6function toHexString(a) {
7 return Array.from(a, b => b.toString(16).padStart(2, '0')).join('');
8}
9
10/**
11 * Generate a UUIDv7 (Time-Sortable Identifier).
12 * @returns {string}
13 * The generated UUIDv7 (`00000000-0000-0000-0000-000000000000`).
14 * @example
15 * let id; console.log(id = generateId());
16 * console.log(new Date(validateId(id)).toLocaleString());
17 */
18export function generateId() {
19 const timestamp = Date.now();
20
21 // Convert the timestamp to a 6-byte hexadecimal string.
22 const timestampHex = timestamp.toString(16).padStart(12, '0');
23
24 // Generate 10 random bytes for the remaining parts.
25 const randomBytes = new Uint8Array(10);
26 crypto.getRandomValues(randomBytes);
27
28 const randomPart1 = randomBytes.subarray(0, 2);
29 const randomPart2 = randomBytes.subarray(2, 4);
30 const randomPart3 = randomBytes.subarray(4);
31
32 randomPart1[0] = (randomPart1[0] & 0x0F) | 0x70; // version
33 randomPart2[0] = (randomPart2[0] & 0x3F) | 0x80; // variant
34
35 return [
36 timestampHex.slice(0, 8), // first 4 bytes of timestamp
37 timestampHex.slice(8, 12), // last 2 bytes of timestamp
38 toHexString(randomPart1), // version 7 (2 bytes)
39 toHexString(randomPart2), // variant+random (2 bytes)
40 toHexString(randomPart3), // remaining 6 bytes
41 ].join('-'); // 00000000-0000-0000-0000-000000000000
42}
43
44/**
45 * Validate a UUIDv7 (Time-Sortable Identifier).
46 * @param {string} id
47 * @returns {number}
48 * The Unix timestamp encoded in the UUIDv7.
49 */
50export function validateId(id) {
51 return parseInt(id.match(re).slice(1, 3).join(''), 16);
52}