UUID1 from UTC Timestamp in Python?
The problem goes like this:
My application is deployed on a remote server with different timezo开发者_StackOverflowne and I want to generate a uuid1 against UTC timestamp. I can't find a way to generate uuid1 from any given timestamp. The reason I want to do this is that I don't want to get into the hassle of calculating my local time where my local time does not observe Daylight saving time and the remote server does and a result the presentation logic becomes cumbersome.
The limitation is that the Timestamp needs to be stored as uuid1. Any idea or workaround for this will be higly appreciated.
the UUID class will do the bit-juggling if you give it the right fragments - http://docs.python.org/library/uuid.html
to get the right components you can copy the the uuid1 code from python2.7:
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)
all you need to do is copy+paste that and modify the timestamp part to use a fixed value (you can ignore the last_timestamp part if you know that your times are distinct - that is just to avoid duplicates when the clock resolution is insufficient).
Here is a function to extract a Unix timestamp from a UUID v1:
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())
Usage:
>>> 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
The Cassandra driver for Python now has a function for this very purpose:
cassandra.util.uuid_from_time()
https://datastax.github.io/python-driver/api/cassandra/util.html#cassandra.util.uuid_from_time
Here is a sample code that will generate a UUID1 from a given integer timestamp
Note that while timestamp part will stay static, a part of the uuid is still random.
You can pass the clock_seq
value if you want the uuid to stay the same
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))
精彩评论