ブラウザ環境では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")