This repository has been archived by the owner on Jul 9, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
Clarify how to represent fractional seconds in UUIDv7 #44
Comments
I think it might be a good idea to include code examples, at least in a few of the most common programming languages, how to encode and decode those timestamps. Basically every programming language I know expresses precision timestamps as integers. For example https://docs.python.org/3/library/time.html#time.time_ns |
Python code example # Enough to represent nanoseconds from time.time_ns()
SUBSEC_BITS = 30
SUBSEC_DECIMAL_DIGITS = 9
def subsec_encode(
value: int,
subsec_bits: int = SUBSEC_BITS,
subsec_decimal_digits: int = SUBSEC_DECIMAL_DIGITS,
) -> int:
return value * 2 ** subsec_bits // 10 ** subsec_decimal_digits
def subsec_decode(
value: int,
subsec_bits: int = SUBSEC_BITS,
subsec_decimal_digits: int = SUBSEC_DECIMAL_DIGITS,
) -> int:
return -(-value * 10 ** subsec_decimal_digits // 2 ** subsec_bits)
def test_millisecond():
print("Testing millisecond conversions.")
for i in range(10 ** 3):
if i % 10 ** 2 == 0:
print(f"{i=} ...")
assert i == subsec_decode(subsec_encode(i, 10, 3), 10, 3)
def test_microsecond():
print("Testing microsecond conversions.")
for i in range(10 ** 6):
if i % 10 ** 5 == 0:
print(f"{i=} ...")
assert i == subsec_decode(subsec_encode(i, 20, 6), 20, 6)
def test_nanosecond():
print("Testing nanosecond conversions.")
for i in range(10 ** 9):
if i % 10 ** 6 == 0:
print(f"{i=} ...")
assert i == subsec_decode(subsec_encode(i, 30, 9), 30, 9)
def main():
import time
timestamp = time.time_ns()
unixts, ns = divmod(timestamp, 10 ** SUBSEC_DECIMAL_DIGITS)
subsec = subsec_encode(ns)
subsec_to_ns = subsec_decode(subsec)
print(f"{timestamp=}")
print(f"{unixts=}")
print(f"{ns=}")
print(f"{subsec=}")
print(f"{subsec_to_ns=}")
test_millisecond()
test_microsecond()
test_nanosecond()
if __name__ == "__main__":
main() Ouput is something like timestamp=1641075060289465000
unixts=1641075060
ns=289465000
subsec=310810677
subsec_to_ns=289465000
Testing millisecond conversions.
i=0 ... Those |
Great code example @oittaa ! |
kyzer-davis
added
UUIDv8
All things UUIDv8 related
and removed
UUIDv7
All things UUIDv7 related
labels
Feb 23, 2022
Merged
Merged
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Some of the UUIDv7 implementations I've seen on GitHub have not implemented fractional seconds correctly. For instance, putting the number of milliseconds directly into the 12 bit field
subsec_a
, thereby using a 0-999 subset of the full 0-4095 range.To prevent this, could the initial descriptions of the
subsec_a
andsubsec_b
fields (around L568 of the-02.txt
draft) make it more explicit that these must use the full range, with an example of what not to do.Currently this isn't spelled out (though discussed in issue #24). For instance:
Section 4.4.1. - UUIDv7 Timestamp Usage
Section 4.4.4.1. - UUIDv7 Encoding
It's only once the reader gets down to L845 that the requirements are spelled out:
Section 4.4.4.2. UUIDv7 Decoding
As an additional suggestion, it would be very helpful if the text could include some examples of uuids and their min/max implied timestamps, to serve as test cases in unit tests.
The text was updated successfully, but these errors were encountered: