ulid
This library implements a Universally Unique Lexicographically Sortable Identifier (ULID) generator.
Note that most backends provide time stamps with lower granularity than required (i.e., seconds but not milliseconds). Also note that, per spec, within the same millisecond, monotonic sort order is not guaranteed.
The generation of ULIDs uses the /dev/urandom
random number
generator when available. This includes macOS, Linux, *BSD, and other
POSIX operating-systems. On Windows, a pseudo-random generator is used
but randomized using the current wall time.
ULIDs can be generated as atoms, lists of characters, or lists of character codes.
See also the ids
and uuid
libraries.
API documentation
Open the ../../docs/library_index.html#ulid link in a web browser.
Loading
To load all entities in this library, load the loader.lgt
file:
| ?- logtalk_load(ulid(loader)).
Testing
To test this library predicates, load the tester.lgt
file:
| ?- logtalk_load(ulid(tester)).
Generating ULIDs
By default, ULIDs are generated as atoms. For example:
| ?- ulid::generate(ULID).
ULID = '01H0J31SYQXHJZWPRAKHQ6YVYH'
yes
To generate a ULID using a list of characters representation, use
instead the ulid/1
parametric object:
| ?- ulid(chars)::generate(ULID).
ULID = ['0','1','H','0','J','3','2','Y','V','5','V','S','P','K','5','P','4','5','G','G','0','9','8','8','M','2']
yes
Similarly, to get a ULID using a list of character codes representation:
| ?- ulid(codes)::generate(ULID).
ULID = [48,49,72,48,74,51,52,66,54,48,55,57,54,49,67,82,70,65,67,51,67,67,86,82,48,66]
yes
It’s also possible to generate ULIDs from a given timestamp, i.e. the
number of milliseconds since the Unix epoch (00:00:00 UTC on January 1,
1970), using the generate/2
predicate. The timestamp must be an
integer. For example, assuming a backend Prolog system providing a
time_stamp/1
predicate returning the Unix epoch in milliseconds:
| ?- time_stamp(Milliseconds), ulid(atom)::generate(Seconds, ULID).
Seconds = 1684245175344, ULID = '01H0JDBQ1GAWJF35C44Y5S97DX'
yes
You can also use timestamp discrete components using the generate/8
predicate. For example:
| ?- ulid(atom)::generate(2023, 5, 17, 16, 23, 38, 591, ULID).
ULID = '01H0N8CDAZK75C5H3BJSGS4VCQ'
yes
To extract the timestamp from a given ULID, use the timestamp/2
and
timestamp/8
predicates. For example:
| ?- ulid(atom)::timestamp('01H0JDBQ1GAWJF35C44Y5S97DX', Milliseconds).
Milliseconds = 1684245175344
yes
| ?- ulid(atom)::timestamp('01H0N8CDAZK75C5H3BJSGS4VCQ', Year, Month, Day, Hours, Minutes, Seconds, Milliseconds).
Year = 2023, Month = 5, Day = 17, Hours = 16, Minutes = 23, Seconds = 38, Milliseconds = 591
yes
Type-checking ULIDs
This library also defines a ulid(Representation)
type for
type-checking ULIDs. For example, with an atom containing invalid
characters:
| ?- type::check(ulid(atom), '01BX5ZIKBKALTAV9OEVGEMMVRY').
uncaught exception: domain_error(ulid,'01BX5ZIKBKALTAV9OEVGEMMVRY')