Generate ULIDs in Delphi

Resources  |  Generate ULIDs in Delphi

Generating a ULID (Universally Unique Lexicographically Sortable Identifier) in Delphi can be done by implementing the ULID algorithm manually, as there isn't a well-known Delphi library for ULID generation. Below is a step-by-step guide and an example implementation.

Step-by-Step Guide to Generate ULID in Delphi

  1. Understand the ULID Components:

    • Timestamp: A 48-bit integer representing the number of milliseconds since the Unix epoch.
    • Randomness: An 80-bit random value.
  2. Combine Timestamp and Randomness:

    • Convert the timestamp to a string.
    • Generate a random value.
    • Combine these to form the ULID.
  3. Base32 Encoding:

    • ULIDs are encoded in a Crockford's Base32 format.

Example Implementation in Delphi

Here is an example code to generate ULID in Delphi:

unit ULIDGenerator;

interface

uses
  System.SysUtils, System.DateUtils, System.Math, System.StrUtils;

type
  TULID = class
  public
    class function Generate: string;
  end;

implementation

const
  ULIDBase32: string = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
  TimestampLength = 10;
  RandomLength = 16;

class function TULID.Generate: string;
var
  Timestamp: Int64;
  RandomPart: TBytes;
  ULID: string;
  I: Integer;
begin
  // Get current Unix timestamp in milliseconds
  Timestamp := DateTimeToUnix(Now, False) * 1000;

  // Convert timestamp to ULIDBase32
  ULID := '';
  for I := 1 to TimestampLength do
  begin
    ULID := ULIDBase32[Timestamp mod 32 + 1] + ULID;
    Timestamp := Timestamp div 32;
  end;

  // Generate random part
  SetLength(RandomPart, RandomLength);
  for I := 0 to RandomLength - 1 do
    RandomPart[I] := Random(256);

  // Convert random part to ULIDBase32
  for I := 0 to RandomLength - 1 do
  begin
    ULID := ULID + ULIDBase32[RandomPart[I] mod 32 + 1];
  end;

  Result := ULID;
end;

end.

Explanation

  1. Timestamp Generation:

    • The DateTimeToUnix function converts the current date and time to Unix time (seconds since epoch).
    • This is multiplied by 1000 to get milliseconds.
  2. Base32 Encoding:

    • The timestamp is converted to a Base32 string using the ULIDBase32 characters.
  3. Random Part Generation:

    • A random 16-byte array is generated.
    • Each byte is converted to a Base32 character.
  4. Combining Parts:

    • The timestamp part and the random part are concatenated to form the ULID.

Usage Example

uses
  ULIDGenerator;

begin
  Writeln(TULID.Generate);
end.

Summary

This implementation of ULID generation in Delphi ensures that the generated ULIDs are compliant with the ULID specification, providing unique, lexicographically sortable, and globally unique identifiers. While there isn't a dedicated Delphi library for ULIDs, this manual implementation follows the ULID standard and can be used in Delphi applications.