Skip to content

Instantly share code, notes, and snippets.

@Andrew-Chen-Wang
Created April 13, 2025 18:47
Show Gist options
  • Save Andrew-Chen-Wang/02339dfd92e72a936fd7294c20e9ce14 to your computer and use it in GitHub Desktop.
Save Andrew-Chen-Wang/02339dfd92e72a936fd7294c20e9ce14 to your computer and use it in GitHub Desktop.

Revisions

  1. Andrew-Chen-Wang created this gist Apr 13, 2025.
    62 changes: 62 additions & 0 deletions uuid8_excluding_day_precision.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,62 @@
    import uuid
    import random
    from datetime import datetime, UTC

    def encode_time_fields(dt: datetime) -> int:
    year = dt.year
    month = dt.month
    hour = dt.hour
    minute = dt.minute
    millisecond = dt.microsecond // 1000

    # Bounds check
    if not (1970 <= year <= 4095):
    raise ValueError("Year out of range")

    # Encode into 40 bits
    encoded = (
    ((year - 1970) << 28) |
    (month << 24) |
    (hour << 19) |
    (minute << 13) |
    (millisecond)
    )
    return encoded # 40 bits

    def generate_uuidv8_custom_time(dt: datetime = None) -> uuid.UUID:
    if dt is None:
    dt = datetime.now(UTC)

    timestamp_bits = encode_time_fields(dt)

    # Fill the remaining 88 bits with randomness
    rand_high = random.getrandbits(88)

    # Combine timestamp and random into a 128-bit integer
    full_bits = (timestamp_bits << 88) | rand_high

    # Insert UUIDv8 version and variant bits
    full_bits &= ~(0xF << 76)
    full_bits |= (0x8 << 76) # version 8

    full_bits &= ~(0xC000 << 48)
    full_bits |= (0x8000 << 48) # variant 1 (10xxxxxx...)

    # Convert to UUID object
    bytes_ = full_bits.to_bytes(16, byteorder="big")
    return uuid.UUID(bytes=bytes_)

    def decode_time_from_uuidv8(u: uuid.UUID):
    int_val = int.from_bytes(u.bytes, byteorder="big")
    timestamp_bits = int_val >> 88

    year = ((timestamp_bits >> 28) & 0xFFF) + 1970
    month = (timestamp_bits >> 24) & 0xF
    hour = (timestamp_bits >> 19) & 0x1F
    minute = (timestamp_bits >> 13) & 0x3F
    millisecond = timestamp_bits & 0x1FFF

    return f"{year:04}-{month:02} {hour:02}:{minute:02}.{millisecond:03}"

    uuid = generate_uuidv8_custom_time() # '03749580-0664-8ad3-ac86-c2532981ef85'
    decode_time_from_uuidv8(uuid) # '2025-04 18:44.6'