Package: ulid-py
ulidUniversally Unique Lexicographically Sortable IdentifierinPython 3.StatusThis project is actively maintained.InstallationTo install ulid frompip:$pipinstallulid-pyTo install ulid from source:$gitclonegit@github.com:ahawker/ulid.git$cdulid&&pythonsetup.pyinstallUsageCreate a brand new ULID.The timestamp value (48-bits) is fromtime.time()with millisecond precision.The randomness value (80-bits) is fromos.urandom().>>>importulid>>>ulid.new()<ULID('01BJQE4QTHMFP0S5J153XCFSP9')>Create a new ULID from an existing 128-bit value, such as aUUID.Supports ULID values asint,bytes,str, andUUIDtypes.>>>importulid,uuid>>>value=uuid.uuid4()>>>valueUUID('0983d0a2-ff15-4d83-8f37-7dd945b5aa39')>>>ulid.from_uuid(value)<ULID('09GF8A5ZRN9P1RYDVXV52VBAHS')>Create a new ULID from an existing timestamp value, such as adatetimeobject.Supports timestamp values asint,float,str,bytes,bytearray,memoryview,datetime,Timestamp, andULIDtypes.>>>importdatetime,ulid>>>ulid.from_timestamp(datetime.datetime(1999,1,1))<ULID('00TM9HX0008S220A3PWSFVNFEH')>Create a new ULID from an existing randomness value.Supports randomness values asint,float,str,bytes,bytearray,memoryview,Randomness, andULIDtypes.>>>importos,ulid>>>randomness=os.urandom(10)>>>ulid.from_randomness(randomness)>>><ULID('01BJQHX2XEDK0VN0GMYWT9JN8S')>For cases when you don't necessarily control the data type (input from external system), you can use theparsemethod
which will attempt to make the correct determination for you. Please note that this will be slightly slower than creating
the instance from the respectivefrom_*method as it needs to make a number of type/conditional checks.Supports values asint,float,str,bytes,bytearray,memoryview,uuid.UUID, andULIDtypes.>>>importulid>>>value=db.model.get_id()## Unsure about datatype -- Could be int, UUID, or string?>>>ulid.parse(value)>>><ULID('0K0EDFETFM8SH912DBBD4ABXSZ')>Once you have a ULID object, there are a number of ways to interact with it.Thetimestampmethod will give you a snapshot view of the first 48-bits of the ULID while therandomnessmethod
will give you a snapshot of the last 80-bits.>>>importulid>>>u=ulid.new()>>>u<ULID('01BJQM7SC7D5VVTG3J68ABFQ3N')>>>>u.timestamp()<Timestamp('01BJQM7SC7')>>>>u.randomness()<Randomness('D5VVTG3J68ABFQ3N')>TheULID,Timestamp, andRandomnessclasses all derive from the same base class, aMemoryView.AMemoryViewprovides thebin,bytes,hex,int,oct, andstr, methods for changing any values representation.>>>importulid>>>u=ulid.new()>>>u<ULID('01BJQMF54D093DXEAWZ6JYRPAQ')>>>>u.timestamp()<Timestamp('01BJQMF54D')>>>>u.timestamp().int1497589322893>>>u.timestamp().bytesb'\x01\\\xafG\x94\x8d'>>>u.timestamp().datetimedatetime.datetime(2017,6,16,5,2,2,893000)>>>u.randomness().bytesb'\x02F\xde\xb9\\\xf9\xa5\xecYW'>>>u.bytes[6:]==u.randomness().bytesTrue>>>u.str'01BJQMF54D093DXEAWZ6JYRPAQ'>>>u.int1810474399624548315999517391436142935>>>u.bin'0b1010111001010111101000111100101001000110100000010010001101101111010111001010111001111100110100101111011000101100101010111'>>>u.hex'0x15caf47948d0246deb95cf9a5ec5957'>>>u.oct'0o12712750745106402215572712717464573054527'AMemoryViewalso provides rich comparison functionality.>>>importdatetime,time,ulid>>>u1=ulid.new()>>>time.sleep(5)>>>u2=ulid.new()>>>u1<u2True>>>u3=ulid.from_timestamp(datetime.datetime(2039,1,1))>>>u1<u2<u3True>>>[u.timestamp().datetimeforuinsorted([u2,u3,u1])][datetime.datetime(2017,6,16,5,7,14,847000),datetime.datetime(2017,6,16,5,7,26,775000),datetime.datetime(2039,1,1,8,0)]Future ItemsCollection of benchmarks to track performance.Backport to Python 2.7?SeeGithub Issuesfor more!GoalsA fast implementation in pure python of the spec with binary format support.ContributingIf you would like to contribute, simply fork the repository, push your changes and send a pull request.
Pull requests will be brought into themasterbranch via a rebase and fast-forward merge with the goal of having a linear branch history with no merge commits.LicenseApache 2.0Why not UUID?UUID can be suboptimal for many uses-cases because:It isn't the most character efficient way of encoding 128 bits of randomnessUUID v1/v2 is impractical in many environments, as it requires access to a unique, stable MAC addressUUID v3/v5 requires a unique seed and produces randomly distributed IDs, which can cause fragmentation in many data structuresUUID v4 provides no other information than randomness which can cause fragmentation in many data structuresULID provides:128-bit compatibility with UUID1.21e+24 unique ULIDs per millisecondLexicographically sortable!Canonically encoded as a 26 character string, as opposed to the 36 character UUIDUses Crockford's base32 for better efficiency and readability (5 bits per character)Case insensitiveNo special characters (URL safe)SpecificationBelow is the current specification of ULID as implemented in this repository.The binary format is implemented.01AN4Z07BY      79KA1307SR9X4MV3

|----------|    |----------------|
 Timestamp          Randomness
  10chars            16chars
   48bits             80bitsComponentsTimestamp48 bit integerUNIX-time in millisecondsWon't run out of space till the year 10895 AD.Randomness80 bitsCryptographically secure source of randomness, if possibleSortingThe left-most character must be sorted first, and the right-most character sorted last (lexical order).
The default ASCII character set must be used. Within the same millisecond, sort order is not guaranteedEncodingCrockford's Base32 is used as shown. This alphabet excludes the letters I, L, O, and U to avoid confusion and abuse.0123456789ABCDEFGHJKMNPQRSTVWXYZBinary Layout and Byte OrderThe components are encoded as 16 octets. Each component is encoded with the Most Significant Byte first (network byte order).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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      32_bit_uint_time_high                    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     16_bit_uint_time_low      |       16_bit_uint_random      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       32_bit_uint_random                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       32_bit_uint_random                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+String Representationttttttttttrrrrrrrrrrrrrrrr

where
t is Timestamp
r is RandomnessLinksOriginal Implementation (Javascript)ulid (python)