Introduction to {ulid}

UUID : Universally Unique Lexicographically Sortable Identifiers

UUID can be suboptimal for many uses-cases because:

Instead, herein is proposed ULID:

ulid() // 01ARZ3NDEKTSV4RRFFQ69G5FAV
 01AN4Z07BY      79KA1307SR9X4MV3

|----------|    |----------------|
 Timestamp          Randomness
   48bits             80bits

Components

Timestamp - 48 bit integer - UNIX-time in milliseconds - Won’t run out of space till the year 10889 AD.

Randomness - 80 bits - Cryptographically secure source of randomness, if possible

Sorting

The 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 guaranteed.

What’s Inside The Tin

The following functions are implemented:

library(ulid)

One

ulid::ULIDgenerate()
#> [1] "0001EHZADJ3VAF00JK8RQ0VMSA"

Many

(u <- ulid::ULIDgenerate(20))
#>  [1] "0001EHZADJX2KPR14TSZFMKXTB" "0001EHZADJ5FDB1RJS00JK7VD8"
#>  [3] "0001EHZADJAJKWC3RJ5XB0J5C6" "0001EHZADJ31KY89G3MJ0ST2PP"
#>  [5] "0001EHZADJ9P2Y02A4NVNGM6DA" "0001EHZADJJZRADMMSZA8THHN8"
#>  [7] "0001EHZADJCDHSV9BV13H44WMC" "0001EHZADJX35M18CQPMHWJX0S"
#>  [9] "0001EHZADJYDY3K788JE1S62A5" "0001EHZADJBX9VP7H1FRJCMP20"
#> [11] "0001EHZADJ9PS9GW3CHC1XQ7Y8" "0001EHZADJ6B5K3ATZHQRYDHKB"
#> [13] "0001EHZADJCADMHTHEHJFEJNYB" "0001EHZADJYXZXWCSCQASE9PK2"
#> [15] "0001EHZADJVM29VN103GZCV04P" "0001EHZADJWTSBHK0799NQ8SBV"
#> [17] "0001EHZADJRTT2H0Q36R3DYJKZ" "0001EHZADJ9H7QHY35Y9R95FKB"
#> [19] "0001EHZADJF1CMESTT5QB18SBZ" "0001EHZADJPFFF01HPMC8AF1FG"

Unmarshal

unmarshal(u)
#>                     ts              rnd
#> 1  2019-07-05 15:49:06 X2KPR14TSZFMKXTB
#> 2  2019-07-05 15:49:06 5FDB1RJS00JK7VD8
#> 3  2019-07-05 15:49:06 AJKWC3RJ5XB0J5C6
#> 4  2019-07-05 15:49:06 31KY89G3MJ0ST2PP
#> 5  2019-07-05 15:49:06 9P2Y02A4NVNGM6DA
#> 6  2019-07-05 15:49:06 JZRADMMSZA8THHN8
#> 7  2019-07-05 15:49:06 CDHSV9BV13H44WMC
#> 8  2019-07-05 15:49:06 X35M18CQPMHWJX0S
#> 9  2019-07-05 15:49:06 YDY3K788JE1S62A5
#> 10 2019-07-05 15:49:06 BX9VP7H1FRJCMP20
#> 11 2019-07-05 15:49:06 9PS9GW3CHC1XQ7Y8
#> 12 2019-07-05 15:49:06 6B5K3ATZHQRYDHKB
#> 13 2019-07-05 15:49:06 CADMHTHEHJFEJNYB
#> 14 2019-07-05 15:49:06 YXZXWCSCQASE9PK2
#> 15 2019-07-05 15:49:06 VM29VN103GZCV04P
#> 16 2019-07-05 15:49:06 WTSBHK0799NQ8SBV
#> 17 2019-07-05 15:49:06 RTT2H0Q36R3DYJKZ
#> 18 2019-07-05 15:49:06 9H7QHY35Y9R95FKB
#> 19 2019-07-05 15:49:06 F1CMESTT5QB18SBZ
#> 20 2019-07-05 15:49:06 PFFF01HPMC8AF1FG

Use defined timestamps

(ut <- ts_generate(as.POSIXct("2017-11-01 15:00:00", origin="1970-01-01")))
#> [1] "0001CZM6DGE8HX3PA2EVFSSV23"

unmarshal(ut)
#>                    ts              rnd
#> 1 2017-11-01 15:00:00 E8HX3PA2EVFSSV23