logo hsb.horse
← ブログ一覧に戻る

ブログ

UUID v7 実装ガイド: JavaScript・Go・Shellで作る

UUID v7 のビット構造、version/variant のビット設定、JavaScript・Go・Shellでの最小実装、実装時のチェック項目、RFCの参照先を1ページで整理。時系列ソートしやすいIDを安全に導入したい開発者向けに、生成ロジックの確認ポイントをまとめた実践ガイド。実装前の確認に使える。

公開日: 更新日:

UUID v7 を実装したいときに必要な要点だけをまとめる。
この記事では、UUID v7 のビット構成、version/variant の立て方、JavaScript・Go・Shellでの最小実装を順に確認できるようにした。

UUID v7 の要点

UUID v7 は 128 ビットで、先頭にミリ秒タイムスタンプを持つ。

フィールドビット数役割
timestamp48Unix time(ms)
ver40111(v7)
rand_a12ランダム値
var210(variant)
rand_b62ランダム値

この構成により、生成時刻順におおむねソートしやすいIDを作れる。

実装時の共通手順

  1. まず16バイトを乱数で埋める
  2. 先頭6バイトを現在時刻(ミリ秒)で上書きする
  3. value[6] の上位4ビットに 0x7(version)を設定する
  4. value[8] の上位2ビットに 10(variant)を設定する

JavaScript / TypeScript の実装例

function uuidV7Bytes(): Uint8Array {
const value = new Uint8Array(16);
crypto.getRandomValues(value);
const timestamp = BigInt(Date.now());
value[0] = Number((timestamp >> 40n) & 0xffn);
value[1] = Number((timestamp >> 32n) & 0xffn);
value[2] = Number((timestamp >> 24n) & 0xffn);
value[3] = Number((timestamp >> 16n) & 0xffn);
value[4] = Number((timestamp >> 8n) & 0xffn);
value[5] = Number(timestamp & 0xffn);
value[6] = (value[6] & 0x0f) | 0x70;
value[8] = (value[8] & 0x3f) | 0x80;
return value;
}

Go の実装例

package main
import (
"crypto/rand"
"fmt"
"time"
)
func uuidV7() ([16]byte, error) {
var value [16]byte
if _, err := rand.Read(value[:]); err != nil {
return value, err
}
timestamp := uint64(time.Now().UnixMilli())
value[0] = byte(timestamp >> 40)
value[1] = byte(timestamp >> 32)
value[2] = byte(timestamp >> 24)
value[3] = byte(timestamp >> 16)
value[4] = byte(timestamp >> 8)
value[5] = byte(timestamp)
value[6] = (value[6] & 0x0F) | 0x70
value[8] = (value[8] & 0x3F) | 0x80
return value, nil
}
func main() {
id, _ := uuidV7()
fmt.Printf("%x\n", id)
}

Shell Script の実装例

#!/bin/sh
uuid_v7() {
timestamp=$(date +%s)000
timestamp_hi=$((timestamp >> 16))
timestamp_lo=$((timestamp & 0xFFFF))
rand_a=0x$(LC_ALL=C tr -dc '0-9a-f' < /dev/urandom | head -c4)
ver_rand_a=$((0x7000 | (0x0FFF & rand_a)))
rand_b_hi=0x$(LC_ALL=C tr -dc '0-9a-f' < /dev/urandom | head -c4)
var_rand_hi=$((0x8000 | (0x3FFF & rand_b_hi)))
rand_b_lo=$(LC_ALL=C tr -dc '0-9a-f' < /dev/urandom | head -c12)
printf "%08x-%04x-%04x-%04x-%s\n" \
"$timestamp_hi" "$timestamp_lo" "$ver_rand_a" "$var_rand_hi" "$rand_b_lo"
}
uuid_v7

POSIX date ではミリ秒を直接扱えないため、実装環境に応じて取得方法の調整が必要になる。

実装チェック項目

  • 同一ミリ秒内で大量生成する場合の衝突リスクを評価する
  • フォーマット(ハイフン付き文字列 or 16バイト)を利用側で統一する
  • DBのインデックス戦略(時系列ソート前提)を先に決める

関連リンク(サイト内)

参考資料(外部)

まとめ

UUID v7 の実装は、どの言語でも「タイムスタンプ埋め込み + version/variant のビット操作」が中心になる。
要件に応じて既存ライブラリを使うか、最小実装を内製するかを選ぶとよい。