Created
September 6, 2022 16:30
-
-
Save jcary741/8b27e5bb821e65457c06e5b6160837dd to your computer and use it in GitHub Desktop.
UUIDv7 in Javascript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Generate a UUIDv7 as a string (see also: https://datatracker.ietf.org/doc/draft-peabody-dispatch-new-uuid-format/) | |
* | |
* This function was translated to javascript from the python implementation here: https://github.com/oittaa/uuid6-python | |
* | |
* The UUIDv7 format is designed to encode a Unix timestamp with | |
* arbitrary sub-second precision. The key property provided by UUIDv7 | |
* is that timestamp values generated by one system and parsed by | |
* another are guaranteed to have sub-second precision of either the | |
* generator or the parser, whichever is less. Additionally, the system | |
* parsing the UUIDv7 value does not need to know which precision was | |
* used during encoding in order to function correctly. | |
* | |
* @license MIT | |
* | |
* @returns {string} | |
*/ | |
export function uuid7() { | |
const version = 7n; | |
// get date.now in nanoseconds as bigint | |
const nanoseconds = BigInt(Date.now()) * BigInt(1000000); | |
const divmod = (dividend, divisor) => { | |
return [dividend / divisor, dividend % divisor]; | |
} | |
const [timestamp_ms, timestamp_ns] = divmod(nanoseconds, 1000000n); | |
let subsec = timestamp_ns * (2n ** 20n) / 1000000n; | |
let subsec_a = subsec >> 8n; | |
let subsec_b = subsec & 0xFFn; | |
let uuid_int = (timestamp_ms & 0xFFFFFFFFFFFFn) << 80n; | |
uuid_int |= subsec_a << 64n; | |
uuid_int |= subsec_b << 54n; | |
uuid_int |= BigInt(Math.floor(Math.random() * Math.pow(2, 54))); | |
// Set the variant to RFC 4122. | |
uuid_int &= ~(0xC000n << 48n) | |
uuid_int |= 0x8000n << 48n | |
// Set the version number. | |
uuid_int &= ~(0xF000n << 64n) | |
uuid_int |= version << 76n | |
// convert uuid_int to a hex string | |
let hex = uuid_int.toString(16) | |
hex = hex.padStart(32,'0'); | |
return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment