You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中创建含时间戳的类MongoDB ObjectId唯一ID

Replicating MongoDB-style Timestamped Unique IDs with Python's Standard Library

Great question! MongoDB's ObjectId is such a clever design—it's compact, unique, and quietly carries the timestamp of when the ID was created. Let's build something just like it using nothing but Python's built-in tools.

Core Breakdown of MongoDB's ObjectId

First, a quick recap of how ObjectId works to guide our implementation:

  • It's a 12-byte binary value, represented as a 24-character hex string
  • First 4 bytes: Unix timestamp (seconds since epoch, big-endian)
  • Next 3 bytes: Machine identifier
  • Next 2 bytes: Process ID
  • Last 3 bytes: Auto-incrementing counter (prevents collisions in the same process)

We can simplify some parts while retaining the key properties: uniqueness and embedded timestamps.

Implementation 1: Full ObjectId Clone

This generates a 24-character hex ID identical to MongoDB's, using only standard libraries:

import time
import secrets
import struct
import binascii

def generate_mongo_like_id():
    # 1. 4-byte timestamp (seconds since epoch, big-endian)
    timestamp = struct.pack('>I', int(time.time()))
    
    # 2. 5 bytes of cryptographically secure random data
    # Combines machine ID, PID, and randomness for cross-process/machine uniqueness
    random_component = secrets.token_bytes(5)
    
    # 3. 3-byte random counter (simpler than maintaining a global counter)
    # Secrets ensures extremely low collision risk here
    counter = secrets.token_bytes(3)
    
    # Combine all parts and convert to hex string
    id_bytes = timestamp + random_component + counter
    return binascii.hexlify(id_bytes).decode('utf-8')

Parsing the Timestamp from the ID

To extract the creation time later, use this helper:

def get_creation_timestamp(object_id_str):
    # Grab the first 8 hex chars (4 bytes) and convert back to integer
    timestamp_bytes = binascii.unhexlify(object_id_str[:8])
    return struct.unpack('>I', timestamp_bytes)[0]

# Example usage:
created_id = generate_mongo_like_id()
creation_time = get_creation_timestamp(created_id)
print(f"ID created at: {time.ctime(creation_time)}")

Implementation 2: Shorter Timestamped IDs

If you want something more compact than 24 characters, we can use Base64 encoding instead of hex. This gives us a 12-character ID (without padding) while keeping the timestamp:

def generate_short_timestamped_id():
    # 4-byte timestamp + 4-byte random data = 8 bytes total
    timestamp = struct.pack('>I', int(time.time()))
    random_part = secrets.token_bytes(4)
    # Encode to Base64 and strip padding/newlines
    return binascii.b2a_base64(timestamp + random_part).decode('utf-8').strip('=\n')

# Parse timestamp from short ID:
def get_timestamp_from_short_id(short_id):
    # Add back padding to make Base64 valid
    padded_id = short_id + '=' * (-len(short_id) % 4)
    decoded_bytes = binascii.a2b_base64(padded_id)
    return struct.unpack('>I', decoded_bytes[:4])[0]

Key Notes

  • Secrets vs. Random: We use secrets.token_bytes() instead of random because it's cryptographically secure, making collision risk extremely low—critical for unique IDs.
  • Counter vs. Random: For most applications, random bytes work fine. If you're in a high-concurrency scenario where you need strict ordering, replace the random counter with a thread-safe incrementing value (use threading.Lock to protect it).
  • Python Version: secrets is available in Python 3.6+. For older versions, use os.urandom() instead, though it's slightly less secure for sensitive use cases.

内容的提问来源于stack exchange,提问作者Jundiaius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:59:32