Developer Interface

ULID

class ulid.ULID(value: bytes | None = None)[source]

The ULID object consists of a timestamp part of 48 bits and of 80 random bits.

 01AN4Z07BY      79KA1307SR9X4MV3
|----------|    |----------------|
 Timestamp          Randomness
   48bits             80bits

You usually create a new ULID-object by calling the default constructor with no arguments. In that case it will fill the timestamp part with the current datetime. To encode the object you usually convert it to a string:

>>> ulid = ULID()
>>> str(ulid)
'01E75PVKXA3GFABX1M1J9NZZNF'
Parameters:

value (bytes, None) – A sequence of 16 bytes representing an encoded ULID.

Raises:

ValueError – If the provided value is not a valid encoded ULID.

classmethod from_bytes(bytes_: bytes) Self[source]

Create a new ULID-object from sequence of 16 bytes.

classmethod from_datetime(value: datetime) Self[source]

Create a new ULID-object from a datetime. The timestamp part of the ULID will be set to the corresponding timestamp of the datetime.

Examples

>>> from datetime import datetime
>>> ULID.from_datetime(datetime.now())
ULID(01E75QRYCAMM1MKQ9NYMYT6SAV)
classmethod from_hex(value: str) Self[source]

Create a new ULID-object from 32 character string of hex values.

classmethod from_int(value: int) Self[source]

Create a new ULID-object from an int.

classmethod from_str(string: str) Self[source]

Create a new ULID-object from a 26 char long string representation.

classmethod from_timestamp(value: float) Self[source]

Create a new ULID-object from a timestamp. The timestamp can be either a float representing the time in seconds (as it would be returned by time.time()) or an int in milliseconds.

Examples

>>> import time
>>> ULID.from_timestamp(time.time())
ULID(01E75QWN5HKQ0JAVX9FG1K4YP4)
classmethod from_uuid(value: uuid.UUID) Self[source]

Create a new ULID-object from a uuid.UUID. The timestamp part will be random in that case.

Examples

>>> from uuid import uuid4
>>> ULID.from_uuid(uuid4())
ULID(27Q506DP7E9YNRXA0XVD8Z5YSG)
classmethod from_uuid7(value: uuid.UUID) Self[source]

Create a new ULID from a UUIDv7 (uuid.UUID version 7).

Extracts the timestamp from the UUIDv7’s first 48 bits (milliseconds since epoch) and the remaining 80 bits as randomness. The timestamp is always transparently preserved, providing perfect round-trip conversion with to_uuid7().

Examples

>>> uuid7 = uuid.UUID("01936c5e-f4c0-7000-8000-000000000000")
>>> ulid = ULID.from_uuid7(uuid7)
>>> ulid.datetime
datetime.datetime(2025, 11, 10, ...)
classmethod parse(value: Any) Self[source]

Create a new ULID-object from a given value.

Note

This method should only be used when the caller is trying to parse a ULID from a value when they’re unsure what format/primitive type it will be given in.

to_uuid() UUID[source]

Convert the ULID to a uuid.UUID.

to_uuid4() UUID[source]

Convert the ULID to a uuid.UUID compliant to version 4 of RFC 4122.

This conversion is destructive in the sense that the uuid.UUID cannot be converted back to the same ULID. This is because the bits for the variant and version information have to be set accordingly changing the original byte sequence.

Examples

>>> ulid = ULID()
>>> uuid = ulid.to_uuid4()
>>> uuid.version
4
to_uuid7(*, compliant: bool = False) UUID[source]

Convert the ULID to a UUIDv7 (uuid.UUID version 7).

UUIDv7 encodes a Unix timestamp in milliseconds in the first 48 bits (just like ULID). The timestamp is always transparently preserved regardless of compliant mode.

Parameters:

compliant – If True, sets RFC 4122 version (0x7) and variant (0b10) bits, losing 6 bits of randomness. If False (default), preserves all 80 bits of randomness by clobbering version/variant bits, enabling perfect round-trip conversion. Most tools (PostgreSQL, standard libraries) accept non-compliant UUIDv7s.

Examples

>>> ulid = ULID()
>>> uuid7 = ulid.to_uuid7()  # Perfect round-trip
>>> assert ULID.from_uuid7(uuid7) == ulid
>>> uuid7_compliant = ulid.to_uuid7(compliant=True)  # RFC 4122 compliant
>>> uuid7_compliant.version
7
property datetime: datetime[source]

Return the timestamp part as timezone-aware datetime in UTC.

Examples

>>> ulid.datetime
datetime.datetime(2020, 4, 30, 14, 33, 27, 560000, tzinfo=datetime.timezone.utc)
property hex: str[source]

Encode the ULID-object as a 32 char sequence of hex values.

property milliseconds: int[source]

The timestamp part as epoch time in milliseconds.

Examples

>>> ulid.milliseconds
1588257207560
property timestamp: float[source]

The timestamp part as epoch time in seconds.

Examples

>>> ulid.timestamp
1588257207.56

Generators

Every ULID is produced by a ULIDGenerator. The bare ULID constructor and the ULID.from_* factory methods delegate to a shared module-level default_generator. Create your own ULIDGenerator to customize the clock, the randomness source, or the MonotonicityPolicy.

class ulid.ULIDGenerator(clock: Callable[[], int] | None = None, randomness: Callable[[int], bytes] | None = None, policy: MonotonicityPolicy | None = None)[source]

Generator for creating universally unique lexicographically sortable identifiers (ULIDs).

Samples a clock for the timestamp, sources entropy for the randomness, and enforces a MonotonicityPolicy so that identifiers generated within the same millisecond are monotonically increasing. Generation is guarded by a lock and is safe to share across threads.

Parameters:
  • clock – A callable returning the current time in milliseconds. Defaults to the system clock.

  • randomness – A callable that, given a timestamp, returns fresh random bytes for the randomness component. Defaults to os.urandom().

  • policy – The MonotonicityPolicy used to resolve randomness on same-millisecond collisions. Defaults to StrictMonotonicPolicy.

generate(timestamp: float | datetime | None = None) ULID[source]

Generate a new ULID monotonically.

Parameters:

timestamp (int, float, datetime, None) – Optional timestamp to set on the ULID.

Returns:

A generated ULID.

Return type:

ULID

ulid.default_generator

The module-level generator used by ULID() and the ULID.from_* constructors. Reassign it to route the default constructors through a custom ULIDGenerator (e.g. a different clock, randomness source, or MonotonicityPolicy):

ulid.default_generator = ULIDGenerator(policy=LaxMonotonicPolicy())

Monotonicity policies

A monotonicity policy decides how the randomness component is resolved when several ULIDs are generated within the same millisecond. Pass an instance to ULIDGenerator. Any object satisfying the MonotonicityPolicy protocol can be used; stateful policies can subclass BaseMonotonicPolicy and only implement the overflow behaviour.

class ulid.MonotonicityPolicy(*args, **kwargs)[source]

Protocol defining the interface for monotonicity and randomness resolution policies.

resolve_randomness(timestamp: int, randomness_source: Callable[[int], bytes]) bytes[source]

Resolve randomness for a given timestamp.

Parameters:
  • timestamp (int) – The current timestamp in milliseconds.

  • randomness_source (RandomnessSource) – A callable to get fresh random bytes.

Returns:

The resolved randomness bytes (80 bits).

Return type:

bytes

class ulid.BaseMonotonicPolicy[source]

Base class for stateful monotonic policies.

class ulid.StrictMonotonicPolicy[source]

Strict monotonicity policy.

Always increments the randomness by 1 if generated within the same millisecond. Raises ValueError on millisecond randomness exhaustion.

class ulid.LaxMonotonicPolicy[source]

Lax monotonicity policy.

Increments the randomness by 1 if generated within the same millisecond. If the randomness overflows, it regenerates fresh randomness instead of raising an error or sleeping.

class ulid.PureRandomPolicy[source]

Pure random policy.

Always generates fresh randomness without enforcing any monotonicity constraints.