我一直在http://www.ietf.org/rfc/rfc4122.txt阅读UUID RFC并尝试使用python uuid
模块。为了便于解释,这里是从规范中取消的UUID图。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time_low |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time_mid | time_hi_and_version |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|clk_seq_hi_res | clk_seq_low | node (0-1) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| node (2-5) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
根据我对规范的解读,最小的type-1 UUID应该有time_low,time_mid,clk_seq_hi_res,clk_seq_low和节点设置为全0,而time_hi_and_version应该将bit 15设置为1.最大的type-1 UUID应将time_low,time_mid,clk_seq_hi_res,clk_seq_low和节点设置为全1,并将time_hi_and_version设置为除12,13和14位之外的所有1。
然而,尝试在python中生成这些失败:
>>> u = uuid.UUID("{00000000-0000-0000-0001-00000000}")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/Cellar/python/2.7.4/Frameworks/Python.framework/Versions/2.7/lib/python2.7/uuid.py", line 134, in __init__
raise ValueError('badly formed hexadecimal UUID string')
ValueError: badly formed hexadecimal UUID string
>>> u = uuid.UUID("{ffffffff-ffff-ffff-fff1-ffffffff}")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/Cellar/python/2.7.4/Frameworks/Python.framework/Versions/2.7/lib/python2.7/uuid.py", line 134, in __init__
raise ValueError('badly formed hexadecimal UUID string')
ValueError: badly formed hexadecimal UUID string
我认为我正在错误地阅读规范,但我不知所措。
答案 0 :(得分:1)
问题不在于您的特定值,而在于您没有足够的值。
你只提供了14个字节的数据而不是16个,这就是它所抱怨的。
UUID
根本没有检查类型1 UUID的要求。如果确实如此,它将无法用于具有不同要求的其他UUID类型。
试试这个:
In [58]: uuid.UUID("{00000000-0000-0000-0000-000000000000}")
Out[58]: UUID('00000000-0000-0000-0000-000000000000')
In [59]: uuid.UUID('{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}')
Out[59]: UUID('ffffffff-ffff-ffff-ffff-ffffffffffff')
与此同时,您显然也混淆了版本和变体,并且使您的字节顺序落后。所以让我们从头开始。
根据我对规格的解读,最小的1型UUID ...... 应该将time_low,time_mid,clk_seq_hi_res,clk_seq_low和节点设置为全0
clk_seq_hi_res
是clock_sequence_hi_and_reserved
的缩写,在4.1.2节中定义为“与变体复用的时钟序列的高字段”。变量在4.1.1中定义,您需要“本文档中指定的变体”,它将两个最高有效位分别设置为1和0。因此,此字段不能全为0或全1。由于这是大多数有效位,并非最不重要,这意味着八位位组8的高半字节必须是(8, 9, a, b)
之一,而不是低位半字节必须是(1, 5, 9, d)
之一{1}}。
,time_hi_and_version应将第15位设置为1。
不,版本号在4.1.3中描述为时间戳的最高4位,版本1定义为0-0-0-1。因此,第15位应该设置为0,因此应该设置为14和13,并且第12位应该设置为1.这意味着八位位组6的整个顶部半字节必须是1,而不是字节7的低半字节。
所以:
00000000-0000-1000-8000-000000000000
ffffffff-ffff-1fff-bfff-ffffffffffff
请注意,这些时间戳表示的日期有点愚蠢。前者是1582年10月15日午夜,后者是在53世纪。*因此,任何 验证版本1 UUID的库都可能拒绝它们。
此外,全0的节点是全0的全球单播MAC地址,我不确定它是否是有效的IEEE-802地址。所有1的节点都可以,因为如果您设置了多播位,则明确允许您使用随机数。
*各种BBC documentaries和associated textbooks解释说,到了49世纪,人类将有时间旅行,这将迫使我们改变我们所有的时间戳技术。