Skip to main content

HLID: a Human Lexicographically (sortable) Identifier

pypi python build tests license

The HLID is a human-readable lexicographically sortable identifier that borrows similar concepts from -

  • ULID (Universally-Unique, Lexicographically-Sortable Identifier) - github.com/ulid
  • UUID7 (Time-ordered UUID with millisecond precision) - ietf.org

HLIDs have the following properties -

  • Time sortable
  • Human readable in UTC timezone
  • 10^4 seconds time resolution (tenth of milliseconds)
  • 8 bits of user-data (two hex chars)
  • 48 bits of nonce; optionally derived from a truncated hmac-sha256 (12x hex chars)
  • Can be swapped with UUID-type or ULID-type values

With all good things there are tradeoffs -

  • These values are not cryptographically secure for inputs into to strong crypto routines.
  • HLID can provide at best tenth-of-millisecond time resolution, whereas UUID7 provides 50 nanosecond resolution.
  • Because the HMAC is truncated, a larger secret value is enforced (128 bits).

For example a HLID value -

    20241105-1108-5200-00ff-8fa646f09a7e
    ^        ^    ^ ^  ^ ^  ^
    |        |    | |  | |  |- 12x hex: nonce-value -or- hmac-value
    |        |    | |  | |- 2x hex: one byte of user-data; 2x hex chars
    |        |    | |+ |- 4x digits: -10^4 seconds; tenth of millisecond
    |        |    |- 2x digits: seconds
    |        |- 4x digits: hours and minutes
    |- 8x digits: year and month and day
    
    All values are zero-padded when required.

Install

pipx install hlid

Usage

Example: HLID attributes

>>> from hlid import HLID
>>> hlid = HLID()

>>> print(str(hlid))
20250213-1615-0320-9000-723da4092594

>>> print(f"{hlid.hex=}")
hlid.hex='20250213161503209000723da4092594'

>>> print(f"{hlid.age=}")
hlid.age=0.000799

>>> print(f"{hlid.time=}")
hlid.time=1739463303.209

>>> print(f"{hlid.datetime=}")
hlid.datetime=datetime.datetime(2025, 2, 13, 16, 15, 3, 209000, tzinfo=datetime.timezone.utc)

Example: Handle existing HLID values

>>> from hlid import HLID

>>> hlid1 = HLID()
>>> hlid2 = HLID(hlid1.hex)
>>> assert hlid1.hex == hlid2.hex

Example: HMAC signed HLIDs

>>> from hlid import hlid, HLID
>>> from uuid import uuid4

>>> secret = uuid4().hex
>>> hlid_signed = hlid(secret=secret)

>>> print(hlid_signed)
20250213-1613-0211-8000-c199fc3695c5

>>> hlid_test = HLID(hlid_signed.hex, secret=secret)
>>> print(hlid_test)
20250213-1613-0211-8000-c199fc3695c5

>>> bad_secret = uuid4().hex
>>> HLID(hlid_signed.hex, secret=bad_secret)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ndejong/.local/venvs/hlid/lib/python3.12/site-packages/hlid/__init__.py", line 65, in __init__
    raise ValueError("HLID fails HMAC check.")
ValueError: HLID fails HMAC check.

Example: User data byte

>>> from hlid import HLID

>>> # Create HLID with custom user data
>>> hlid = HLID(user_data="ff")
>>> print(f"{hlid.user_data=}")
hlid.user_data='ff'

>>> # Extract user data from existing HLID
>>> existing = HLID("20250213-1615-0320-90ff-723da4092594")
>>> print(f"{existing.user_data=}")
existing.user_data='ff'

Example: Sorting and comparison

>>> from hlid import HLID

>>> # HLIDs are lexicographically sortable
>>> hlid1 = HLID()
>>> hlid2 = HLID()
>>> hlid3 = HLID()

>>> assert hlid1 < hlid2 < hlid3
>>> sorted_hlids = sorted([hlid3, hlid1, hlid2])
>>> assert sorted_hlids == [hlid1, hlid2, hlid3]

Example: Creating HLIDs from specific datetimes

>>> from hlid import HLID
>>> from datetime import datetime, timezone

>>> # Create HLID for a specific point in time
>>> dt = datetime(2024, 11, 5, 11, 8, 52, 520000, tzinfo=timezone.utc)
>>> hlid = HLID.from_datetime(dt)
>>> print(hlid)
20241105-1108-5252-0000-c8f3a1b2d4e5

>>> print(f"{hlid.datetime=}")
hlid.datetime=datetime.datetime(2024, 11, 5, 11, 8, 52, 520000, tzinfo=datetime.timezone.utc)

Metadata

Release files for hlid 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hlid 0.2.2
File Size Uploaded
hlid-0.2.2.tar.gz 11.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hlid 0.2.2
File Interpreter ABI Platform
hlid-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 18.3 kB

Release files / hlid-0.2.2.tar.gz

Download URL hlid-0.2.2.tar.gz
Size 11.2 kB
Tags Source
SHA-256 checksum
How to use checksums
26de87185e0faa4d04ecfc186736029c82d060b763dda86cb958da60ed901f3c
BLAKE2b-256 checksum
How to use checksums
6d116460eba2294eb1676ddf47e7438034b0d3d1bff5956e13671d15845bbf45
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.1.1 CPython/3.12.3

Release files / hlid-0.2.2-py3-none-any.whl

Download URL hlid-0.2.2-py3-none-any.whl
Size 7.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
68009c1cbe6188eadfecee4bbf6c80098ab233b983765c0f38b1548f61fac840
BLAKE2b-256 checksum
How to use checksums
e1b5624fbedb0f35b977c7b458787207d93f4cad1f4ef50e5e129877b0fa132e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.1.1 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files

0.1.4

2 release files

0.1.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page