Publish package, v1.0.0

This commit is contained in:
Leo Vasanko 2025-07-03 13:27:12 -06:00
commit 94f31c7d0b
4 changed files with 122 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
__pycache__/
dist/
.*
!.gitignore
*.lock

52
README.md Normal file
View File

@ -0,0 +1,52 @@
# UUIDv7 for Python
A simple module for generating UUIDv7 that contain creation
timestamps. Another function for extracting the time of an UUID.
Note: As of writing, Python has no UUIDv7 support. There's an abandoned package `uuid7` that uses a draft RFC with incorrect timestamps (some two centuries off). These modules conflict, uninstall the other one.
- **Standard compliant**: Follows the final UUIDv7 [specification](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7).
- **Pythonic**: Uses stdlib `datetime` and `UUID` facilities rather than milliseconds or bare strings.
## Installation
```sh
pip install uuid7-standard
```
Or for your project using [uv](https://docs.astral.sh/uv/):
```sh
uv add uuid7-standard
```
## Usage
```python
import uuid7
# Create a random UUIDv7 with current timestamp
u = uuid7.create()
print(str(u), u.bytes)
# Create with specific timestamp
from datetime import datetime, UTC
when = datetime(1970, 1, 1, tzinfo=UTC)
u = uuid7.create(when)
# Extract timestamp
from uuid import UUID
u = UUID('00000000-0000-7dac-b3e3-ecb571bb3e2f')
timestamp = uuid7.time(u) # 1970-01-01 UTC
```
### `create(when: datetime?) -> UUID`
Create a UUIDv7 with timestamp-based ordering.
The current time is used, unless `when` is passed as datetime (local time or timezone-aware) This is useful e.g. for creating a bunch of UUIDv7 with precisely the same timestamp.
### `time(u: UUID|str) -> datetime`
Extract the timestamp from a UUIDv7. Raises ValueError if the UUID is not a UUIDv7.

31
pyproject.toml Normal file
View File

@ -0,0 +1,31 @@
[project]
name = "uuid7-standard"
version = "1.0.0"
description = "UUIDv7 with the final standard. Not to be confused with the uuid7 package on pypi, based on a draft version that was very different."
readme = "README.md"
requires-python = ">=3.10"
dependencies = []
authors = [
{name = "Leo Vasanko"},
]
keywords = ["uuid", "uuid7", "timestamp", "ordering", "database", "primary-key"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"License :: Public Domain",
"Programming Language :: Python :: 3",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Utilities",
]
[project.urls]
Homepage = "https://git.zi.fi/leo/uuid7-python"
Repository = "https://github.com/LeoVasanko/uuid7-python"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["uuid7.py"]

34
uuid7.py Normal file
View File

@ -0,0 +1,34 @@
from datetime import datetime
from datetime import timezone as _tz
from secrets import token_bytes as _token_bytes
from uuid import UUID
__all__ = ["create", "time"]
def create(when: datetime | None = None) -> UUID:
"""Create a UUIDv7 with timestamp-based ordering.
Args:
when: Timestamp to use. Defaults to current time.
"""
if when is None:
when = datetime.now()
ts = int(when.timestamp() * 1000).to_bytes(6, "big")
rand = bytearray(_token_bytes(10))
rand[0] = (rand[0] & 0x0F) | 0x70
rand[2] = (rand[2] & 0x3F) | 0x80
return UUID(bytes=ts + rand)
def time(u: UUID | str) -> datetime:
"""Extract the timestamp from a UUIDv7.
Raises ValueError if u is not a UUID version 7.
"""
if not isinstance(u, UUID):
u = UUID(u)
if u.version != 7:
raise ValueError("Not a UUIDv7")
ts = int.from_bytes(u.bytes[:6], "big")
return datetime.fromtimestamp(ts / 1000, tz=_tz.utc)