ブラウザ環境ではDate.now()が正しい値を返さないため注意が必要である
function generateUUIDv7() {
const fromTo = (buffer, start, end) =>
Array.from(buffer.slice(start, end))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
// 1. 現在のUNIXタイムスタンプ(ミリ秒)を取得
const value = BigInt(Date.now());
const buffer = new Uint8Array(16);
// 2. 先頭48ビット(6バイト)にタイムスタンプを書き込み
for (let i = 0; i < 6; i++) {
buffer[i] = Number((value >> BigInt((5 - i) * 8)) & 0xffn);
}
// 3. 残りの領域に暗号論的ランダム値を設定
crypto.getRandomValues(buffer.subarray(6));
// 4. バージョン (7) とバリアント (10xx) のビットを設定
buffer[6] = (buffer[6] & 0x0f) | 0x70; // version 7
buffer[8] = (buffer[8] & 0x3f) | 0x80; // variant 10
// 5. 文字列フォーマットに変換
return `${fromTo(buffer, 0, 4)}-${fromTo(buffer, 4, 6)}-${fromTo(buffer, 6, 8)}-${fromTo(buffer, 8, 10)}-${fromTo(buffer, 10, 16)}`;
}
dv.paragraph(generateUUIDv7());$= [Array.from((now=>new Uint8Array(6).map((n,i)=>Number((now>>BigInt((5-i)*8))&0xffn)))(BigInt(Date.now()))).flat(),crypto.getRandomValues(new Uint8Array(1))[0]&0x0f|0x70,crypto.getRandomValues(new Uint8Array(1))[0],crypto.getRandomValues(new Uint8Array(1))[0]&0x3f|0x80,Array.from(crypto.getRandomValues(new Uint8Array(7))).flat()].flat().map(b=>b.toString(16).padStart(2,'0')).join('').replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/,"$1-$2-$3-$4-$5")