Skip to content

Instantly share code, notes, and snippets.

@flipeador
Last active January 8, 2025 23:52
Show Gist options
  • Save flipeador/878e735b9f6432ff7006975627104693 to your computer and use it in GitHub Desktop.
Save flipeador/878e735b9f6432ff7006975627104693 to your computer and use it in GitHub Desktop.
JavaScript UUIDv7 (Time-Sortable Identifier) for NodeJS and the browser.
/**
* JavaScript UUIDv7 (Time-Sortable Identifier) for NodeJS and the browser.
* https://gist.github.com/flipeador/878e735b9f6432ff7006975627104693
*
*
* IMPORTANT:
* Quickly made with the help of ChatGPT, not suitable for use in production.
* This implementation may not be fully compliant with the UUIDv7 specification.
*/
const re = /^([0-9a-f]{8})-([0-9a-f]{4})-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
/**
* Convert a byte array to an hexadecimal string.
*/
function toHexString(a) {
return Array.from(a, b => b.toString(16).padStart(2, '0')).join('');
}
/**
* Generate a UUIDv7 (Time-Sortable Identifier).
* @returns {string}
* The generated UUIDv7 (`00000000-0000-0000-0000-000000000000`).
* @example
* let id; console.log(id = generateId());
* console.log(new Date(validateId(id)).toLocaleString());
*/
export function generateId() {
const timestamp = Date.now();
// Convert the timestamp to a 6-byte hexadecimal string.
const timestampHex = timestamp.toString(16).padStart(12, '0');
// Generate 10 random bytes for the remaining parts.
const randomBytes = new Uint8Array(10);
crypto.getRandomValues(randomBytes);
const randomPart1 = randomBytes.subarray(0, 2);
const randomPart2 = randomBytes.subarray(2, 4);
const randomPart3 = randomBytes.subarray(4);
randomPart1[0] = (randomPart1[0] & 0x0F) | 0x70; // version
randomPart2[0] = (randomPart2[0] & 0x3F) | 0x80; // variant
return [
timestampHex.slice(0, 8), // first 4 bytes of timestamp
timestampHex.slice(8, 12), // last 2 bytes of timestamp
toHexString(randomPart1), // version 7 (2 bytes)
toHexString(randomPart2), // variant+random (2 bytes)
toHexString(randomPart3), // remaining 6 bytes
].join('-'); // 00000000-0000-0000-0000-000000000000
}
/**
* Validate a UUIDv7 (Time-Sortable Identifier).
* @param {string} id
* @returns {number}
* The Unix timestamp encoded in the UUIDv7.
*/
export function validateId(id) {
return parseInt(id.match(re).slice(1, 3).join(''), 16);
}
@flipeador
Copy link
Author

Reserved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment