如何在Python中从UTC时间戳生成UUID1?
问题是这样的:
我的应用程序部署在一个远程服务器上,这个服务器的时区和我本地的不一样。我想根据UTC时间戳生成一个uuid1,但我找不到从任何给定时间戳生成uuid1的方法。我之所以想这样做,是因为我不想麻烦地去计算我本地的时间,特别是因为我的本地时间不遵循夏令时,而远程服务器却遵循,这样一来,处理逻辑就变得很复杂。
限制是时间戳需要以uuid1的形式存储。如果有人有任何想法或解决办法,我将非常感激。
4 个回答
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
3
现在,Python的Cassandra驱动程序有一个专门用来实现这个功能的函数:
cassandra.util.uuid_from_time()
https://datastax.github.io/python-driver/api/cassandra/util.html#cassandra.util.uuid_from_time
4
UUID类会处理一些复杂的位运算,只要你给它正确的部分就行 - http://docs.python.org/library/uuid.html
要获取正确的组件,你可以从Python 2.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)
你只需要复制粘贴这段代码,然后把时间戳的部分改成一个固定的值(如果你知道你的时间是不同的,可以忽略最后的时间戳部分 - 这个部分主要是为了避免在时钟精度不足时出现重复的UUID)。