2

我一直在http://www.ietf.org/rfc/rfc4122.txt阅读 UUID RFC并尝试使用 pythonuuid模块。为了便于解释,这里是从规范中提取的 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 和 node 设置为全 0,并且 time_hi_and_version 应该有第 15 位设置为 1。最大的 type-1 UUID 应该有 time_low 、time_mid、clk_seq_hi_res、clk_seq_low 和 node 设置为全 1,并且 time_hi_and_version 设置为全 1,但位 12、13 和 14 除外。

但是,尝试在 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

我假设我正在错误地阅读规范,但我很茫然。

4

1 回答 1

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 和 node 设置为全 0

clk_seq_hi_res是 的缩写clock_sequence_hi_and_reserved,在第 4.1.2 节中定义为“与变体复用的时钟序列的高场”。变体在 4.1.1 中定义,并且您想要“本文档中指定的变体”,它将两个最高有效位分别设置为 1 和 0。因此,该字段不能全为 0,或全为 1。由于这是重要的位,而不是最不重要的,这意味着八位字节的高半字节必须是 之一(8, 9, a, b),而不是低半字节必须是 之一(1, 5, 9, d)

,并且 time_hi_and_version 应该将第 15 位设置为 1。

不,版本号在 4.1.3 中描述为时间戳的最高有效 4 位,版本 1 定义为 0-0-0-1。因此,第 15 位应设置为 0,14 和 13 也应设置为 0,第 12 位应设置为 1。这意味着 8 位字节 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 纪录片相关教科书所解释的,到 49 世纪,人类将进行时间旅行,这将迫使我们改变所有时间戳技术。

于 2013-06-02T05:02:06.633 回答