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.

UUID attributesPython 2.5+Live demo
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

AttributeTypeMeaning
time_lowintThe first 32 bits (first hex group).
time_midintThe next 16 bits (second group).
time_hi_versionintThe next 16 bits (third group); its top 4 bits are the version.
clock_seq_hi_variantintThe next 8 bits; its top bits are the variant.
clock_seq_lowintThe next 8 bits.
nodeintThe last 48 bits (last group); the MAC address in a version 1 UUID.
timeintDerived: 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_seqintDerived: 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
True

Pitfalls

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.