Skip to content

Commit 4234110

Browse files
committed
Add notes on monotonicity
1 parent c4c1a5f commit 4234110

File tree

1 file changed

+46
-16
lines changed

1 file changed

+46
-16
lines changed

README.md

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,29 @@ ulid() // 01ARZ3NDEKTSV4RRFFQ69G5FAV
4747
// You can also input a seed time which will consistently
4848
// give you the same string for the time component. This is
4949
// useful for migrating to ulid.
50-
//
51-
// Note that multiple calls with the same seed time will
52-
// still monotonically increase the random component for
53-
// strict sort order.
5450
ulid(1469918176385) // 01ARYZ6S41TSV4RRFFQ69G5FAV
5551
```
5652

53+
#### Monotonic ULIDs
54+
55+
To generate monotonically increasing ULIDs, create a monotonic counter.
56+
57+
```javascript
58+
import { createMonotonic } from 'ulid'
59+
60+
const ulid = createMonotonic()
61+
62+
// Strict ordering for the same timestamp, by incrementing the least-significant random bit by 1
63+
ulid(150000) // 000XAL6S41ACTAV9WEVGEMMVR8
64+
ulid(150000) // 000XAL6S41ACTAV9WEVGEMMVR9
65+
ulid(150000) // 000XAL6S41ACTAV9WEVGEMMVRA
66+
ulid(150000) // 000XAL6S41ACTAV9WEVGEMMVRB
67+
ulid(150000) // 000XAL6S41ACTAV9WEVGEMMVRC
68+
69+
// Even if a lower timestamp is passed (or generated), it will preserve sort order
70+
ulid(100000) // 000XAL6S41ACTAV9WEVGEMMVRD
71+
```
72+
5773
## Implementations in other languages
5874

5975
From the community!
@@ -124,18 +140,6 @@ Below is the current specification of ULID as implemented in this repository.
124140

125141
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
126142

127-
#### Monotonicity
128-
129-
When generating a ULID within the same millisecond, we can provide some
130-
guarantees regarding sort order. Namely, if the same millisecond is detected, the `random` component is incremented by 1 bit in the least significant bit position (with carrying). For example:
131-
132-
```javascript
133-
ulid() // 01BX5ZZKBKACTAV9WEVGEMMVRZ
134-
ulid() // 01BX5ZZKBKACTAV9WEVGEMMVS0
135-
```
136-
137-
If, in the extremely unlikely event that, you manage to generate at most 80 ^ 2 ULIDs within the same millisecond, or cause the random component to overflow in any other way, the generation will fail.
138-
139143
### Canonical String Representation
140144

141145
```
@@ -154,6 +158,32 @@ Crockford's Base32 is used as shown. This alphabet excludes the letters I, L, O,
154158
0123456789ABCDEFGHJKMNPQRSTVWXYZ
155159
```
156160

161+
### Monotonicity
162+
163+
When generating a ULID within the same millisecond, we can provide some
164+
guarantees regarding sort order. Namely, if the same millisecond is detected, the `random` component is incremented by 1 bit in the least significant bit position (with carrying). For example:
165+
166+
```javascript
167+
// Assume that these calls occur within the same millisecond
168+
ulid() // 01BX5ZZKBKACTAV9WEVGEMMVRZ
169+
ulid() // 01BX5ZZKBKACTAV9WEVGEMMVS0
170+
```
171+
172+
If, in the extremely unlikely event that, you manage to generate at most 80 ^ 2 ULIDs within the same millisecond, or cause the random component to overflow with less, the generation will fail.
173+
174+
```javascript
175+
// Assume that these calls occur within the same millisecond
176+
ulid() // 01BX5ZZKBKACTAV9WEVGEMMVRY
177+
ulid() // 01BX5ZZKBKACTAV9WEVGEMMVRZ
178+
ulid() // 01BX5ZZKBKACTAV9WEVGEMMVS0
179+
ulid() // 01BX5ZZKBKACTAV9WEVGEMMVS1
180+
....
181+
ulid() // 01BX5ZZKBKZZZZZZZZZZZZZZZX
182+
ulid() // 01BX5ZZKBKZZZZZZZZZZZZZZZY
183+
ulid() // 01BX5ZZKBKZZZZZZZZZZZZZZZZ
184+
ulid() // throw new Error()!
185+
```
186+
157187
#### Overflow Errors when Parsing Base32 Strings
158188

159189
Technically, a 26 character Base32 encoded string can contain 130 bits of information, whereas a ULID must only contain 128 bits. Therefore, the largest valid ULID encoded in Base32 is `7ZZZZZZZZZZZZZZZZZZZZZZZZZ`, which corresponds to an epoch time of `281474976710655`.

0 commit comments

Comments
 (0)