Python中如何从UTC时间戳生成UUID1?

4
问题描述如下:
我的应用部署在具有不同时区的远程服务器上,我想根据UTC时间戳生成uuid1。我找不到从任何给定时间戳生成uuid1的方法。我之所以这样做,是因为我不想计算我的本地时间,我的本地时间不遵守夏令时,而远程服务器遵守夏令时,结果呈现逻辑变得繁琐。
限制是时间戳需要存储为uuid1。非常感谢任何想法或解决方法。

限制在于时间戳需要存储为uuid1。这是什么意思?时间戳并不是uuid。uuid通过众所周知的算法生成;它们与时间戳不可互换。如果你说的uuid1是指版本1的uuid,那么可以看出它取决于MAC地址:http://en.wikipedia.org/wiki/Universally_unique_identifier - Cheeso
这是因为它需要存储在Cassandra中,其中条目按TimeUUIDType排序,该类型是uuid1。稍后可以使用众所周知的算法将其转换为时间戳。 - SoulReaver
@cheeso - uuid类型1同时使用MAC地址和时间戳。请参阅RFC http://www.ietf.org/rfc/rfc4122.txt。 - andrew cooke
4个回答

4

如果您提供正确的片段,UUID类将进行位操作 - http://docs.python.org/library/uuid.html

要获取正确的组件,您可以从Python2.7复制uuid1代码:

def uuid1(node=None, clock_seq=None):
        """Generate a UUID from a host ID, sequence number, and the current time.
        If 'node' is not given, getnode() is used to obtain the hardware
        address.  If 'clock_seq' is given, it is used as the sequence number;
        otherwise a random 14-bit sequence number is chosen."""
    # When the system provides a version-1 UUID generator, use it (but don't
    # use UuidCreate here because its UUIDs don't conform to RFC 4122).
    if _uuid_generate_time and node is clock_seq is None:
        _buffer = ctypes.create_string_buffer(16)
        _uuid_generate_time(_buffer)
        return UUID(bytes=_buffer.raw)
    global _last_timestamp
    import time
    nanoseconds = int(time.time() * 1e9)
    # 0x01b21dd213814000 is the number of 100-ns intervals between the
    # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
    timestamp = int(nanoseconds//100) + 0x01b21dd213814000L
    if _last_timestamp is not None and timestamp <= _last_timestamp:
        timestamp = _last_timestamp + 1
    _last_timestamp = timestamp
    if clock_seq is None:
        import random
        clock_seq = random.randrange(1<<14L) # instead of stable storage
    time_low = timestamp & 0xffffffffL
    time_mid = (timestamp >> 32L) & 0xffffL
    time_hi_version = (timestamp >> 48L) & 0x0fffL
    clock_seq_low = clock_seq & 0xffL
    clock_seq_hi_variant = (clock_seq >> 8L) & 0x3fL
    if node is None:
        node = getnode()
    return UUID(fields=(time_low, time_mid, time_hi_version,
                        clock_seq_hi_variant, clock_seq_low, node), version=1)

您只需要复制+粘贴并修改时间戳部分以使用固定值(如果您知道您的时间戳是不同的,则可以忽略last_timestamp部分 - 这只是为了避免在时钟分辨率不足时出现重复)。


3

2

这里有一个从UUID v1中提取Unix时间戳的函数:

def uuid1_unix_timestamp(uuid_):
    '''
    Extract timestamp from UUID1.

    Params
    ------
    uuid_ : uuid.UUID
        UUID v1 instance.

    Returns
    -------
    float
        Unix timestamp.
    '''
    import datetime as dt

    # UUID v1 timestamp is measured from [00:00:00, 1 October 1582][1].
    #
    # [1]: https://quora.com/Why-UUID-v1-timestamp-measured-from-00-00-00-00-15-October-
    return (uuid_.time * 1e-7 - (dt.datetime.utcfromtimestamp(0) -
                                 dt.datetime(1582, 10, 15)).total_seconds())

使用方法:

>>> import datetime as dt
>>> # Extract timestamp from a new Python UUID v1 instance.
>>> uuid1_unix_timestamp(uuid.uuid1())
1533834175.8219986
>>> # Convert timestamp from Python UUID v1 to Python datetime.
>>> timestamp = uuid1_unix_timestamp(uuid.uuid1())
>>> dt.datetime.utcfromtimestamp(timestamp)
datetime.datetime(2018, 8, 9, 17, 3, 10, 122999)
>>> # Extract timestamp from a UUID v1 string.
>>> uuid_ = uuid.UUID('4101d7a1-9bf6-11e8-b86d-9cb6d0e37eb4')
>>> uuid1_unix_timestamp(uuid_)
1533834258.9699993

0
这里是一个示例代码,可以从给定的整数时间戳生成UUID1。
请注意,虽然时间戳部分将保持静态,但UUID的一部分仍然是随机的。 如果您希望UUID保持不变,可以传递clock_seq值。
import uuid

try:
    import unittest.mock as mock
except ImportError:
    import mock


def fixed_uuid1(timestamp, *args, **kwargs):
    """Returns a UUID1 from a fixed timestamp"""
    with mock.patch('uuid._uuid_generate_time', None), \
            mock.patch('uuid._last_timestamp', None), \
            mock.patch('time.time', return_value=timestamp):
        return uuid.uuid1(*args, **kwargs)


print(fixed_uuid1(0))
print(fixed_uuid1(0, clock_seq=0))
print(fixed_uuid1(1565627822.303553))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接