UUID.fields / time / clock_seq / node
Every UUID splits into 32 + 16 + 16 + 8 + 8 + 48 bits. The names come from version 1, where they really hold a time, a clock sequence and the MAC address; for random and name-based UUIDs they are just slices of the bits.
Common call
u.fields
Returns
(time_low, time_mid, time_hi_version, clock_seq_hi_variant, clock_seq_low, node)
Replaces
Slicing str(u) into groups and int(..., 16) each
Watch out
time, clock_seq and node only mean something for version 1 UUIDs
u.fields · u.time_low · u.time_mid · u.time_hi_version · u.clock_seq_hi_variant · u.clock_seq_low · u.node · u.time · u.clock_seq
→ tuple[int, int, int, int, int, int] / int
Demo
Live evaluation
The six fields as ints.
Try:
Inputs
textstra UUID string
Code
import uuid uuid.UUID('12345678-1234-5678-1234-567812345678').fields
Result
(305419896, 4660, 22136, 18, 52, 95073701484152)
The docs' uuid1 example decodes to 2006-06-10 and the NAMESPACE_DNS constant to 1998-02-04, both real creation times. The same arithmetic on a uuid4 gives a date that means nothing: its "time" bits are random. Integer division by 10 drops the last 100 ns digit, because timedelta only stores microseconds.
Attributes
| Attribute | Type | Meaning |
|---|---|---|
| time_low | int | The first 32 bits (first hex group). |
| time_mid | int | The next 16 bits (second group). |
| time_hi_version | int | The next 16 bits (third group); its top 4 bits are the version. |
| clock_seq_hi_variant | int | The next 8 bits; its top bits are the variant. |
| clock_seq_low | int | The next 8 bits. |
| node | int | The last 48 bits (last group); the MAC address in a version 1 UUID. |
| time | int | Derived: the 60-bit timestamp, time_hi_version without the version bits, then time_mid, then time_low. In version 1: 100-nanosecond intervals since 1582-10-15. |
| clock_seq | int | Derived: the 14-bit sequence number from clock_seq_hi_variant (variant bits removed) and clock_seq_low. |
Common patterns
Timestamp of a uuid1
Only for version 1 (check u.version first). The result is UTC.
import uuid from datetime import datetime, timedelta, timezone if u.version == 1: made = datetime(1582, 10, 15, tzinfo=timezone.utc) + timedelta(microseconds=u.time // 10)
MAC address of a uuid1
node formatted as six colon-separated bytes.
import uuid mac = ':'.join(f'{b:02x}' for b in u.node.to_bytes(6))
Build from fields
The fields tuple round-trips through UUID(fields=...).
import uuid same = uuid.UUID(fields=u.fields)
Examples
1. The six fields
import uuid
uuid.UUID('12345678-1234-5678-1234-567812345678').fields
Returns
(305419896, 4660, 22136, 18, 52, 95073701484152)2. Fields one by one
import uuid
u = uuid.UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
(u.time_low, u.time_mid, u.time_hi_version, u.clock_seq_hi_variant, u.clock_seq_low)
Returns
(2819197978, 63598, 4570, 189, 26)3. node is the last group
import uuid
hex(uuid.UUID('a8098c1a-f86e-11da-bd1a-00112444be1e').node)
Returns
'0x112444be1e'4. time: 60-bit timestamp
import uuid
hex(uuid.UUID('a8098c1a-f86e-11da-bd1a-00112444be1e').time)
Returns
'0x1daf86ea8098c1a'5. clock_seq drops the variant bits
import uuid
u = uuid.UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
(u.clock_seq_hi_variant, u.clock_seq)
Returns
(189, 15642)6. A uuid1 back to its date
import uuid
from datetime import datetime, timedelta
u = uuid.UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
datetime(1582, 10, 15) + timedelta(microseconds=u.time // 10)
Returns
datetime.datetime(2006, 6, 10, 10, 48, 31, 13993)7. Round trip through fields
import uuid
u = uuid.uuid4()
uuid.UUID(fields=u.fields) == u
Returns
TruePitfalls
1. Reading a time from a uuid4
Every field exists on every UUID, so nothing stops you from decoding a random UUID as a date. Check the version first.
decode anything
import uuid from datetime import datetime, timedelta u = uuid.UUID('16fd2706-8baf-433b-82eb-8c7fada847da') (datetime(1582, 10, 15) + timedelta(microseconds=u.time // 10)).year
2320
check version
import uuid u = uuid.UUID('16fd2706-8baf-433b-82eb-8c7fada847da') u.version == 1
False
2. Out-of-range fields
UUID(fields=...) checks each field against its bit width and names the field (1 to 6) that does not fit.
49-bit node
import uuid uuid.UUID(fields=(1, 2, 3, 4, 5, 1 << 48))
ValueError: field 6 out of range (need a 48-bit value)
mask to 48 bits
import uuid uuid.UUID(fields=(1, 2, 3, 4, 5, (1 << 48) - 1))
UUID('00000001-0002-0003-0405-ffffffffffff')
When to use
Use it
- Inspecting version 1 UUIDs: creation time, clock sequence, MAC address
- Building or decoding UUIDs field by field for a protocol
Reach for something else
- Random or name-based UUIDs → the fields carry no meaning there
- Just the text → str(u) or u.hex
Notes
CPython impl
Properties over self.int in Lib/uuid.py: time_low = int >> 96, time_mid = (int >> 80) & 0xffff, …, node = int & 0xffffffffffff; time = ((time_hi_version & 0x0fff) << 48) | (time_mid << 32) | time_low
Epoch
The version 1 timestamp counts 100 ns intervals from 1582-10-15 00:00:00; uuid.py adds 0x01b21dd213814000 to convert from the Unix epoch
3.14
The 3.14 docs add that time also holds the timestamp of the new version 6 and 7 UUIDs (milliseconds since the Unix epoch for version 7)
FAQ
u.time is the count of 100-nanosecond intervals since 1582-10-15. datetime(1582, 10, 15) + timedelta(microseconds=u.time // 10) turns it into a (UTC) datetime.