Publish package, v1.0.0
This commit is contained in:
commit
94f31c7d0b
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
__pycache__/
|
||||
dist/
|
||||
.*
|
||||
!.gitignore
|
||||
*.lock
|
52
README.md
Normal file
52
README.md
Normal 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
31
pyproject.toml
Normal 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
34
uuid7.py
Normal 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)
|
Loading…
x
Reference in New Issue
Block a user