-
Notifications
You must be signed in to change notification settings - Fork 0
/
flaxid.go
53 lines (43 loc) · 1.25 KB
/
flaxid.go
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
package flaxid
import (
"math"
"math/big"
"math/rand"
"strconv"
"strings"
"time"
)
// Start at January 1st, 2015. Same as the reference python implementation
const EpochStart = 1420070400000
const TotalBits = 96
const TimestampBits = 40
const RandomBits = TotalBits - TimestampBits
// Modified Base 64 alphabet that preserves lexicographical ordering
const Base64Alphabet = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"_abcdefghijklmnopqrstuvwxyz"
func zeroPad(str string, length int) string {
return strings.Repeat("0", length-len(str)) + str
}
func base64LexEncode(num *big.Int) string {
bnum := zeroPad(num.Text(2), TotalBits)
s := ""
for i := 0; i <= TotalBits-6; i += 6 {
x, _ := strconv.ParseInt(bnum[i:i+6], 2, 64)
s += string(Base64Alphabet[x])
}
return s
}
func getFlaxIDNum(timestamp time.Time) *big.Int {
ms := big.NewInt((timestamp.UnixNano() / 1e6) - EpochStart)
ms.Lsh(ms, RandomBits)
randomNum := big.NewInt(0)
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
randomNum.Rand(rnd, big.NewInt(int64(math.Pow(2, RandomBits))))
return ms.Add(ms, randomNum)
}
func New() string {
return base64LexEncode(getFlaxIDNum(time.Now()))
}
func ForTimestamp(timestamp time.Time) string {
return base64LexEncode(getFlaxIDNum(timestamp))
}