Skip to content

Commit f2f850f

Browse files
authored
Proper v7 subsec encoding (#13)
1 parent 3c0fda7 commit f2f850f

2 files changed

Lines changed: 17 additions & 10 deletions

File tree

src/uuid6/__init__.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
https://github.com/uuid6/uuid6-ietf-draft.
55
"""
66

7+
import math
8+
import secrets
9+
import time
710
from uuid import UUID
811

912

@@ -43,7 +46,7 @@ def time(self) -> int:
4346
| (self.time_hi_version & 0x0FFF)
4447
)
4548
if self.version == 7:
46-
return self.unixts * 10 ** 9 + self.subsec
49+
return self.unixts * 10 ** 9 + _subsec_decode(self.subsec)
4750
return super().time
4851

4952
@property
@@ -52,11 +55,17 @@ def unixts(self) -> int:
5255

5356

5457
def _getrandbits(k: int) -> int:
55-
import secrets
56-
5758
return secrets.randbits(k)
5859

5960

61+
def _subsec_decode(value: int) -> int:
62+
return math.ceil(value * 10 ** 9 / 2 ** 30)
63+
64+
65+
def _subsec_encode(value: int) -> int:
66+
return value * 2 ** 30 // 10 ** 9
67+
68+
6069
_last_v6_timestamp = None
6170
_last_v7_timestamp = None
6271

@@ -67,7 +76,6 @@ def uuid6(clock_seq: int = None) -> UUID:
6776
otherwise a random 14-bit sequence number is chosen."""
6877

6978
global _last_v6_timestamp
70-
import time
7179

7280
nanoseconds = time.time_ns()
7381
# 0x01b21dd213814000 is the number of 100-ns intervals between the
@@ -98,16 +106,16 @@ def uuid7() -> UUID:
98106
used during encoding in order to function correctly."""
99107

100108
global _last_v7_timestamp
101-
import time
102109

103110
nanoseconds = time.time_ns()
104111
if _last_v7_timestamp is not None and nanoseconds <= _last_v7_timestamp:
105112
nanoseconds = _last_v7_timestamp + 1
106113
_last_v7_timestamp = nanoseconds
107114
timestamp_s, timestamp_ns = divmod(nanoseconds, 10 ** 9)
108-
subsec_a = timestamp_ns >> 18
109-
subsec_b = (timestamp_ns >> 6) & 0x0FFF
110-
subsec_c = timestamp_ns & 0x3F
115+
subsec = _subsec_encode(timestamp_ns)
116+
subsec_a = subsec >> 18
117+
subsec_b = (subsec >> 6) & 0x0FFF
118+
subsec_c = subsec & 0x3F
111119
rand = _getrandbits(56)
112120
uuid_int = (timestamp_s & 0x0FFFFFFFFF) << 92
113121
uuid_int |= subsec_a << 80

test/test_uuid6.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,9 @@ def test_invalid_version(self):
4646
@patch("time.time_ns", return_value=1234)
4747
def test_uuid7_same_nanosecond(self, mocktime):
4848
uuid7_1 = uuid7()
49-
for _ in range(10):
49+
for _ in range(1000):
5050
uuid7_2 = uuid7()
5151
self.assertLess(uuid7_1, uuid7_2)
52-
self.assertEqual(uuid7_1.int >> 56, (uuid7_2.int >> 56) - 1)
5352
uuid7_1 = uuid7_2
5453

5554
@patch("uuid6._last_v6_timestamp", 1)

0 commit comments

Comments
 (0)