Yet another unique identifier generator - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: General (https://python-forum.io/forum-1.html) +--- Forum: Code sharing (https://python-forum.io/forum-5.html) +--- Thread: Yet another unique identifier generator (/thread-40744.html) |
Yet another unique identifier generator - Gribouillis - Sep-16-2023 This small module generates unique ever 11 letters identifiers by converting the number of nanoseconds since 1970 to a string. I know there are many ways to generate unique strings, one of them being using the uuid module, but I like to have a simpler solution #!/usr/bin/env python # SPDX-FileCopyrightText: 2023 Eric Ringeisen # SPDX-License-Identifier: MIT """Module idunique.py - generate unique identifiers """ from time import perf_counter_ns import datetime as dt from string import ascii_letters __version__ = "2023.09.17" TZINFO_UTC = dt.timezone.utc UNIX_TIME_ZERO = dt.datetime(year=1970, month=1, day=1, tzinfo=TZINFO_UTC) ASCII_LETTERS = str("").join(sorted(ascii_letters)) NLETTERS = len(ASCII_LETTERS) NANO_PER_MICRO = 1000 NANO_PER_SEC = 1_000_000_000 NANO_PER_DAY = 24 * 3600 * NANO_PER_SEC @(lambda x: x()) class static: """Helper class for Identifier implementation""" def __init__(self): tdelta = dt.datetime.now(tz=TZINFO_UTC) - UNIX_TIME_ZERO self.base = ( tdelta.days * NANO_PER_DAY + tdelta.seconds * NANO_PER_SEC + tdelta.microseconds * NANO_PER_MICRO ) self.zero = perf_counter_ns() self._xA = -ord("A") self._xa = -ord("a") + ASCII_LETTERS.index("a") @staticmethod def euclid(n: int): while n: n, r = divmod(n, NLETTERS) yield ASCII_LETTERS[r] @staticmethod def euclid_inv(s): n = 0 for c in s: n = ord(c) + (static._xA if c < "a" else static._xa) + n * NLETTERS return n class Identifier(str): @classmethod def new(cls): """Create a new unique Identifier based on time The Identifier is created by converting the approximate number of nanoseconds since the Unix time zero to a string of lowercase and uppercase letters. If created between 1975 and 2208, this string has exactly 11 letters. """ d = 0 while d == 0: p = perf_counter_ns() d = p - static.zero static.zero = p static.base += d return cls(("".join(static.euclid(static.base)))[::-1]) def __int__(self): return static.euclid_inv(self) def timedelta(self): return dt.timedelta(microseconds=int(self) / 1000) def datetime(self): return UNIX_TIME_ZERO + self.timedelta() def sort_key(self): """Key to sort Identifiers according to their creation time. This is only useful if some are not between 1975 and 2208 because all Identifiers between these dates have 11 characters""" return (len(self), str(self)) if __name__ == "__main__": for i in range(5): j = Identifier.new() print(j, int(j), j.datetime(), j.sort_key())
RE: Yet another unique identifier generator - Larz60+ - Sep-16-2023 sounds like how linux time is generated https://unixtime.org/ RE: Yet another unique identifier generator - Gribouillis - Sep-16-2023 (Sep-16-2023, 11:15 AM)Larz60+ Wrote: sounds like how linux time is generated https://unixtime.org/I updated the generator by replacing datetime.now() with datetime.now(tz=datetime.timezone.utc) in order to use the UTC time instead of my local time. For some reason it appears to be 2 seconds ahead of the linux time displayed by the web page.
RE: Yet another unique identifier generator - Larz60+ - Sep-17-2023 That would be a fun one to figure out (if you had nothing else in the world to do). |