HLID: a Human Lexicographically (sortable) Identifier
Project description
HLID: a Human Lexicographically (sortable) Identifier
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)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
hlid-0.2.2.tar.gz
(11.2 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
hlid-0.2.2-py3-none-any.whl
(7.1 kB
view details)
File details
Details for the file hlid-0.2.2.tar.gz.
File metadata
- Download URL: hlid-0.2.2.tar.gz
- Upload date:
- Size: 11.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26de87185e0faa4d04ecfc186736029c82d060b763dda86cb958da60ed901f3c
|
|
| MD5 |
b9e91d876b41b090ee9dcfafa63f9d94
|
|
| BLAKE2b-256 |
6d116460eba2294eb1676ddf47e7438034b0d3d1bff5956e13671d15845bbf45
|
File details
Details for the file hlid-0.2.2-py3-none-any.whl.
File metadata
- Download URL: hlid-0.2.2-py3-none-any.whl
- Upload date:
- Size: 7.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
68009c1cbe6188eadfecee4bbf6c80098ab233b983765c0f38b1548f61fac840
|
|
| MD5 |
fccd2977407c1df12186401c777f95b1
|
|
| BLAKE2b-256 |
e1b5624fbedb0f35b977c7b458787207d93f4cad1f4ef50e5e129877b0fa132e
|