Sequential Unique Short & Sortable Identifier
Project description
Serial-Id
Sequential Unique Short & Sortable Identifier
It is a short sequential identifier that is random but sortable and only uses 80 bits. First 40 bits are for timestamp and rest of the 40 bits are used for randomness.
Why's Serial-Id?
This is a conversion of ahawker/ulid 128 bits implementation to short 80 bits identifier with purpose of sortability and uses Crockford's Base32 encoding
Installation
To install serial-id from github:
$ pip install --upgrade git+https://github.com/mysteryjeans/serial-id.git
To install serial-id from source:
$ git clone https://github.com/mysteryjeans/serial-id.git
$ cd serial-id && python setup.py install
Usage
Create a brand new SerialId.
The timestamp value (40-bits) is from time.time() with centiseconds precision.
The randomness value (40-bits) is from os.urandom().
import serialid
serialid.new()
<SerialId('4t8ax5bs-6gvqk2sy')>
Sequential Ids but with randomness
Create a new SerialId from an existing 80-bit value with guaranteed sort order.
import serialid
seq_ids = []
new_sid = serialid.new()
for _ in range(0, 1000):
new_sid = serialid.new_seq(new_sid)
seq_ids.append(new_sid)
seq_ids[:10]
Create a new SerialId from an existing timestamp value, such as a datetime object.
Supports timestamp values as int, float, str, bytes, bytearray, memoryview, datetime, Timestamp, and SerialId types.
import datetime, serialid
serialid.from_timestamp(datetime.datetime(1999, 1, 1))
<SerialId('4t8ax5bs-6gvqk2sy')>
Create a new SerialId from an existing randomness value.
Supports randomness values as int, float, str, bytes, bytearray, memoryview, Randomness types.
import os, serialid
randomness = os.urandom(10)
serialid.from_randomness(randomness)
<SerialId('4t8ax5bs-sgx82mz4')>
For cases when you don't necessarily control the data type (input from external system), you can use the parse method
which will attempt to make the correct determination for you. Please note that this will be slightly slower than creating
the instance from the respective from_* method as it needs to make a number of type/conditional checks.
Supports values as int, float, str, bytes, bytearray, memoryview, and SerialId types.
import serialid
value = db.model.get_id() ## Unsure about datatype -- Could be int or string?
serialid.parse(value) # Parses from str, int, float, bytes ...
<SerialId('4t8ax5bs-vp61yjkk')>
Once you have a SerailId object, there are a number of ways to interact with it.
The timestamp method will give you a snapshot view of the first 40-bits of the SerialId while the randomness method
will give you a snapshot of the last 40-bits.
import serialid
id = serialid.new()
id
<SerialId('4t8ax5bs-vp61yjkk')>
id.timestamp()
<Timestamp('4t8ax5bs')>
id.randomness()
<Randomness('vp61yjkk')>
The SerialId, Timestamp, and Randomness classes all derive from the same base class, a MemoryView.
A MemoryView provides the bin, bytes, hex, int, oct, and str, methods for changing any values representation.
import serialid
u = serialid.new()
u
<SerialId('4t8ax5bs-vp61yjkk')
u.timestamp()
<Timestamp('4t8ax5bs')>
u.timestamp().int
165636436000
u.timestamp().bytes
b'&\x90\xb3j\x13'
u.timestamp().datetime
datetime.datetime(2022, 6, 28, 2, 12, 1, 190000)
u.randomness().bytes
b'\x01c.)\xfa'
u.bytes[5:] == u.randomness().bytes
True
u.str
'4t8ax5bs-vp61yjkk'
u.int
182119165340642244955695
u.bin
'0b100110100100001011001100100001111000001001111100111101001011100000111000101111'
u.hex
'0x2690b321e09f3d2e0e2f'
u.oct
'0o46441314417011747513407057'
A MemoryView also provides rich comparison functionality.
import datetime, time, serialid
u1 = serialid.new()
time.sleep(5)
u2 = serialid.new()
u1 < u2
True
u3 = serialid.from_timestamp(datetime.datetime(2039, 1, 1))
u1 < u2 < u3
True
[u.timestamp().datetime for u in sorted([u2, u3, u1])]
[datetime.datetime(2022, 6, 28, 2, 24, 56, 700000),
datetime.datetime(2022, 6, 28, 2, 25, 1, 710000),
datetime.datetime(2039, 1, 1, 0, 0)]
Contributing
If you would like to contribute, simply fork the repository, push your changes and send a pull request.
Pull requests will be brought into the master branch via a rebase and fast-forward merge with the goal of having a linear branch history with no merge commits.
License
Why not ULID?
SerailId provides:
- 80-bit sortable Ids
- 1099511627776 unique Serial Ids per centisecond 100th of a second
- Lexicographically sortable!
- Canonically encoded as a 16 character string, as opposed to the 24 character ULID
- Uses Crockford's base32 for better efficiency and readability (5 bits per character)
- Case insensitive
- No special characters (URL safe)
Specification
Below is the current specification of ULID as implemented in this repository.
The binary format is implemented.
4t8ax5bs vp61yjkk
|----------| |----------|
Timestamp Randomness
8chars 8chars
40bits 40bits
Components
Timestamp
- 40 bit integer
- UNIX-time in centiseconds
- Won't run out of space till the year 2322 (300 years).
Randomness
- 40 bits
- Cryptographically secure source of randomness, if possible
Sorting
The left-most character must be sorted first, and the right-most character sorted last (lexical order).
The default ASCII character set must be used. Within the same centiseconds, use serialid.new_seq to guaranteed sort order
Encoding
Crockford's Base32 is used as shown. This alphabet excludes the letters I, L, O, and U to avoid confusion and abuse.
0123456789abcdefghjkmnpqrstvwxyz
String Representation
ttttttttrrrrrrrr
where
t is Timestamp
r is Randomness
Links
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
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
File details
Details for the file serial-id-0.1.tar.gz.
File metadata
- Download URL: serial-id-0.1.tar.gz
- Upload date:
- Size: 12.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.9.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f97b50869851e39da7597c515f5da5b2d3d0d9f75edfb81c1b74005ea530928
|
|
| MD5 |
871c662f97bc27bd1b5b78a8f314ae72
|
|
| BLAKE2b-256 |
c4d7fa28df150a1aa8e9e96b7d222b4373592ae2b7997e6f3124b6732a45ee94
|
File details
Details for the file serial_id-0.1-py3.9.egg.
File metadata
- Download URL: serial_id-0.1-py3.9.egg
- Upload date:
- Size: 13.7 kB
- Tags: Egg
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.1 CPython/3.9.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4b7120f3b33f36c47da67da8d2c3ab83df7f7ee4ec5ff33c9fc9d9fb4a7bd25a
|
|
| MD5 |
4956aa6ebff0b4cdf4b132979cd53b8c
|
|
| BLAKE2b-256 |
9e5e4668afa5ebb4a2fe763bf986e50cc9e83677859f456c0b1dfa36a022cd39
|