โ† Back to Blog

How to Parse a UUID

2026-04-18 ยท 5 min read

Internal Structure of UUID

UUID's 128 bits are divided into multiple fields per RFC 4122, represented in xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx format: the first hexadecimal character of the third group (M) is the version number (1-7); the first hexadecimal character of the fourth group (N) is the variant identifier (8/9/a/b indicating RFC 4122 variant); for UUID v1, the first three groups (time_low + time_mid + time_hi_and_version) store a 60-bit timestamp; for UUID v7, the first 12 hexadecimal characters (48 bits) store a Unix millisecond timestamp; for UUID v4, except for version and variant bits, the rest is random data with no parseable content.

Quick UUID Version Identification

# ไปŽๅญ—็ฌฆไธฒๅฟซ้€Ÿ่ฏปๅ–็‰ˆๆœฌ๏ผˆไธ้œ€่ฆ่งฃๆžๅฏน่ฑก๏ผ‰
def get_version(uuid_str: str) -> int:
    """UUID ๆ ผๅผ๏ผšxxxxxxxx-xxxx-Vxxx-xxxx-xxxxxxxxxxxx
    ็ฌฌ15ไฝ๏ผˆ0-indexed๏ผ‰ๆ˜ฏ็‰ˆๆœฌๅท"""
    uuid_clean = uuid_str.replace('-', '').replace('{', '').replace('}', '')
    if len(uuid_clean) != 32:
        raise ValueError("Not a valid UUID")
    version_char = uuid_clean[12]  # ็ฌฌ13ไฝ๏ผˆ0-indexed:12๏ผ‰ๆ˜ฏ็‰ˆๆœฌ
    return int(version_char, 16)

# ๆต‹่ฏ•
uuids = {
    'v1': '550e8400-e29b-11d4-a716-446655440000',
    'v4': '550e8400-e29b-41d4-a716-446655440000',
    'v7': '018e2a4f-53a0-7000-9fc6-e4a59b818e85',
}
for name, uid in uuids.items():
    print(f"{name}: version = {get_version(uid)}")

Parsing UUID v1 Timestamp

# Python๏ผš่งฃๆž UUID v1 ๆ—ถ้—ดๆˆณ
import uuid
from datetime import datetime, timezone

def parse_uuid_v1_timestamp(uuid_str: str) -> datetime:
    """ไปŽ UUID v1 ๆๅ–็”Ÿๆˆๆ—ถ้—ด"""
    u = uuid.UUID(uuid_str)
    if u.version != 1:
        raise ValueError(f"Expected UUID v1, got v{u.version}")

    # UUID v1 ๆ—ถ้—ดๆˆณๆ˜ฏไปŽ 1582-10-15 00:00:00 UTC ๅผ€ๅง‹็š„ 100 ็บณ็ง’ๆ•ฐ
    # Python uuid ๅบ“ๅทฒ็ป่ฎก็ฎ—ๅฅฝไบ† u.time
    GREGORIAN_EPOCH_OFFSET = 0x01b21dd213814000  # ๆ ผ้‡Œ้ซ˜ๅˆฉๅކ่ตท็‚นๅˆฐ Unix ่ตท็‚น็š„ 100ns ๆ•ฐ

    # ่ฝฌๆขไธบ Unix ๆ—ถ้—ดๆˆณ๏ผˆ็ง’๏ผ‰
    unix_ts = (u.time - GREGORIAN_EPOCH_OFFSET) / 1e7
    return datetime.fromtimestamp(unix_ts, tz=timezone.utc)

# ไฝฟ็”จ
v1_uuid = str(uuid.uuid1())
print(f"UUID v1: {v1_uuid}")
print(f"Generated at: {parse_uuid_v1_timestamp(v1_uuid)}")

# ๆˆ–็›ดๆŽฅไฝฟ็”จ uuid ๅบ“็š„ time ๅฑžๆ€ง
u = uuid.UUID(v1_uuid)
print(f"Raw timestamp (100ns since 1582-10-15): {u.time}")
print(f"Node (MAC address): {hex(u.node)}")

Parsing UUID v7 Timestamp

# UUID v7 ๆ—ถ้—ดๆˆณ่งฃๆž๏ผˆ้ซ˜ 48 ไฝๆ˜ฏ Unix ๆฏซ็ง’ๆ—ถ้—ดๆˆณ๏ผ‰
from datetime import datetime, timezone

def parse_uuid_v7_timestamp(uuid_str: str) -> datetime:
    """ไปŽ UUID v7 ๆๅ–็”Ÿๆˆๆ—ถ้—ด๏ผˆๆฏซ็ง’็ฒพๅบฆ๏ผ‰"""
    # ็งป้™ค่ฟžๅญ—็ฌฆ
    clean = uuid_str.replace('-', '')
    # ๅ–้ซ˜ 48 ไฝ๏ผˆๅ‰ 12 ไธชๅๅ…ญ่ฟ›ๅˆถๅญ—็ฌฆ๏ผ‰
    timestamp_ms = int(clean[:12], 16)
    return datetime.fromtimestamp(timestamp_ms / 1000, tz=timezone.utc)

# ้ชŒ่ฏ็‰ˆๆœฌๆ˜ฏ 7
def is_uuid_v7(uuid_str: str) -> bool:
    clean = uuid_str.replace('-', '')
    return len(clean) == 32 and clean[12] == '7'

# JavaScript ็คบไพ‹
# function parseUUIDv7Timestamp(uuid) {
#   const hex = uuid.replace(/-/g, '');
#   const timestampMs = parseInt(hex.slice(0, 12), 16);
#   return new Date(timestampMs);
# }

# ไฝฟ็”จ็คบไพ‹๏ผˆ้œ€่ฆๅฎ‰่ฃ… uuid7 ๅบ“๏ผ‰
# import uuid7
# uid = str(uuid7.uuid7())
# print(f"UUID v7: {uid}")
# print(f"Generated at: {parse_uuid_v7_timestamp(uid)}")

Complete UUID Parser

# ๅฎŒๆ•ด UUID ไฟกๆฏ่งฃๆžๅ™จ
import uuid
from datetime import datetime, timezone

def parse_uuid_info(uuid_str: str) -> dict:
    """่งฃๆž UUID ็š„ๆ‰€ๆœ‰ๅฏ็”จไฟกๆฏ"""
    u = uuid.UUID(uuid_str)

    info = {
        'input': uuid_str,
        'canonical': str(u),       # ๆ ‡ๅ‡†ๅฐๅ†™ๆ ผๅผ
        'hex': u.hex,              # ๆ— ่ฟžๅญ—็ฌฆ
        'version': u.version,
        'variant': str(u.variant),
        'bytes_count': len(u.bytes),
        'int_value': u.int,
    }

    if u.version == 1:
        # v1: ๆ—ถ้—ดๆˆณ + MAC
        OFFSET = 0x01b21dd213814000
        unix_ts = (u.time - OFFSET) / 1e7
        info['timestamp'] = datetime.fromtimestamp(unix_ts, tz=timezone.utc).isoformat()
        info['node'] = hex(u.node)
        info['clock_seq'] = u.clock_seq
    elif u.version == 7:
        # v7: Unix ๆฏซ็ง’ๆ—ถ้—ดๆˆณ
        ts_ms = int(u.hex[:12], 16)
        info['timestamp'] = datetime.fromtimestamp(ts_ms / 1000, tz=timezone.utc).isoformat()
    elif u.version in (3, 5):
        # v3/v5: ็กฎๅฎšๆ€ง๏ผŒไปŽๅ‘ฝๅ็ฉบ้—ดๅ’Œๅ็งฐๆดพ็”Ÿ
        hash_type = 'MD5' if u.version == 3 else 'SHA-1'
        info['hash_type'] = hash_type
        info['note'] = 'Deterministic UUID from namespace + name'

    return info

# ๆต‹่ฏ•
for uid in ['550e8400-e29b-41d4-a716-446655440000',
            uuid.uuid1(), uuid.uuid4(), uuid.uuid5(uuid.NAMESPACE_URL, 'test')]:
    info = parse_uuid_info(str(uid))
    print(info)

Bulk Extraction of Time Information from Database

-- MySQL๏ผšไปŽ UUID v1 ๆๅ–ๆ—ถ้—ด๏ผˆไฝฟ็”จๆœ‰ๅบ UUID๏ผ‰
SELECT
    BIN_TO_UUID(id, 1) as uuid_str,
    -- UUID_TO_BIN ็ฌฌไบŒไธชๅ‚ๆ•ฐ 1 ่กจ็คบๅทฒ้‡ๆŽ’๏ผŒ้œ€่ฆ่ฟ˜ๅŽŸ
    FROM_UNIXTIME(
        (CONV(HEX(SUBSTRING(id, 1, 8)), 16, 10) - 122192928000000000) / 10000000
    ) as generated_at
FROM orders
ORDER BY id
LIMIT 10;

-- PostgreSQL๏ผšUUID v7 ็š„ๆ—ถ้—ดๆๅ–
SELECT
    id,
    -- ๆๅ–้ซ˜ 48 ไฝไฝœไธบๆฏซ็ง’ๆ—ถ้—ดๆˆณ
    to_timestamp(
        (('x' || left(replace(id::text, '-', ''), 12))::bit(48)::bigint) / 1000.0
    ) AT TIME ZONE 'UTC' as generated_at
FROM events
ORDER BY id
LIMIT 10;

Try the free tool now

Use Free Tool โ†’