ULID Dates
A Python utility to determine ULID prefixes for date ranges.
This can be useful for querying databases or logs for ULIDs that fall within a specific time period.
For example by finding the prefixes for the start and end of a time range, you can efficiently scan for records within that range.
If id is a ULID, you can then fine items between two time prefixes ... WHERE id >= 'start_prefix' AND id < 'end_prefix'.
Installation
Install the package using pip:
pip install ulid-dates
Alternatively, using uv:
uv pip install ulid-dates
Usage
Basic Usage
from datetime import datetime, timedelta
from ulid_dates import ulid_prefix_range_for_dates
start_date = datetime(2023, 1, 1)
end_date = start_date + timedelta(days=1)
start_prefix, end_prefix = ulid_prefix_range_for_dates(start_date, end_date)
print(f"ULID prefix for {start_date}: {start_prefix}")
print(f"ULID prefix for {end_date}: {end_prefix}")
Advanced Usage: Querying a DynamoDB GSI
A use case for this library is to query a database for records that have UUIDs within a specific time range. If you are using ULIDs as sort keys in a DynamoDB Global Secondary Index (GSI), you can use the generated prefixes to efficiently query for records created within a certain period.
Here is an example of how you might query a GSI in a DynamoDB table where logs for orders are stored within the PKI but with a common lookup value and a sort that contains a UUID.
import boto3
from boto3.dynamodb.conditions import Key
from datetime import datetime, timedelta
from ulid_dates import ulid_prefix_range_for_dates
# 1. Configure DynamoDB table and GSI query parameters
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('my-application-single-table')
gsi_name = 'lookup-index'
# 2. Generate the ULID prefixes for the date range
start_date = datetime.now() - timedelta(days=7)
end_date = datetime.now()
start_prefix, end_prefix = ulid_prefix_range_for_dates(start_date, end_date)
# 3. Query the GSI using the ULID prefixes
# This assumes the GSI partition key is 'logs' and the sort key is 'created_at' (a ULID).
response = table.query(
IndexName=gsi_name,
KeyConditionExpression=Key('lookup').eq('Order#Logs#')
& Key('sort').between(
f"Order#Log#{start_prefix}",
f"Order#Log#{end_prefix}"
)
)
# 4. Print the results
items = response.get('Items', [])
print(f"Found {len(items)} logs.")
Development
To set up the development environment:
- Clone the repository.
- Create a virtual environment and activate it.
- Install the dependencies in editable mode.
Using pip:
pip install -e .[dev]
Alternatively, using uv:
uv pip install -e .[dev]
Running Tests
To run the tests, use pytest:
pytest
Metadata
Release files for ulid-dates 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ulid_dates-0.2.0.tar.gz | 5.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ulid_dates-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 9.5 kB
Release files / ulid_dates-0.2.0.tar.gz
| Download URL | ulid_dates-0.2.0.tar.gz |
|---|---|
| Size | 5.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
220ebb787d882b9bebee592bbc4f222b6712c0fc64124fdb028f0cd84c76dab0
|
|
BLAKE2b-256 checksum How to use checksums |
1bb79f4a8d4305de0e886523a532f89526b45db2a3fa5349c757268f07c5818d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.13
|
Release files / ulid_dates-0.2.0-py3-none-any.whl
| Download URL | ulid_dates-0.2.0-py3-none-any.whl |
|---|---|
| Size | 4.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
45502dddbf54376e48446d293517eeefb5c3a2c5830cf15b5f6c85822e17caa8
|
|
BLAKE2b-256 checksum How to use checksums |
cdb29e4bdd79ca3b64719f82dfe6fd2b923e48730fff94e90eda504f74ac4c50
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.8.13
|