-
Notifications
You must be signed in to change notification settings - Fork 7
/
ULID.pas
80 lines (66 loc) · 1.77 KB
/
ULID.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
unit ULID;
interface
{
ULID: Universally Unique Lexicographically Sortable Identifier
String Representation: ttttttttttrrrrrrrrrrrrrrrr
where t is Timestamp
r is Randomness
For more information see: https://github.com/martinusso/ulid/blob/master/README.md
}
function CreateULID: string;
function EncodeTime(Time: Int64): string;
implementation
uses
DateUtils,
SysUtils,
Windows;
const
ENCODING: array[0..31] of string = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X',
'Y', 'Z'); // Crockford's Base32
ENCODING_LENGTH = Length(ENCODING);
function CreateULID: string;
function UNIXTimeInMilliseconds: Int64;
var
ST: SystemTime;
DT: TDateTime;
begin
GetSystemTime(ST);
DT := EncodeDate(ST.wYear, ST.wMonth, ST.wDay) +
SysUtils.EncodeTime(ST.wHour, ST.wMinute, ST.wSecond, ST.wMilliseconds);
Result := DateUtils.MilliSecondsBetween(DT, UnixDateDelta);
end;
begin
Result := EncodeTime(UNIXTimeInMilliseconds) + EncodeRandom;
end;
function EncodeRandom: string;
const
ENCODED_RANDOM_LENGTH = 16;
var
I: Word;
Rand: Integer;
begin
Result := '';
for I := ENCODED_RANDOM_LENGTH downto 1 do
begin
Rand := Trunc(ENCODING_LENGTH * Random);
Result := ENCODING[Rand] + Result;
end;
end;
function EncodeTime(Time: Int64): string;
const
ENCODED_TIME_LENGTH = 10;
var
I: Word;
M: Integer;
begin
Result := '';
for I := ENCODED_TIME_LENGTH downto 1 do
begin
M := (Time mod ENCODING_LENGTH);
Result := ENCODING[M] + Result;
Time := Trunc((Time - M) / ENCODING_LENGTH);
end;
end;
end.