ulid.go (2435B)
1 // GoToSocial 2 // Copyright (C) GoToSocial Authors admin@gotosocial.org 3 // SPDX-License-Identifier: AGPL-3.0-or-later 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package id 19 20 import ( 21 "crypto/rand" 22 "math/big" 23 "time" 24 25 "github.com/oklog/ulid" 26 ) 27 28 const ( 29 Highest = "ZZZZZZZZZZZZZZZZZZZZZZZZZZ" // Highest is the highest possible ULID 30 Lowest = "00000000000000000000000000" // Lowest is the lowest possible ULID 31 randomRange = 631152381 // ~20 years in seconds 32 ) 33 34 // ULID represents a Universally Unique Lexicographically Sortable Identifier of 26 characters. See https://github.com/oklog/ulid 35 type ULID string 36 37 // NewULID returns a new ULID string using the current time. 38 func NewULID() string { 39 ulid, err := ulid.New( 40 ulid.Timestamp(time.Now()), rand.Reader, 41 ) 42 if err != nil { 43 panic(err) 44 } 45 return ulid.String() 46 } 47 48 // NewULIDFromTime returns a new ULID string using the given time, or an error if something goes wrong. 49 func NewULIDFromTime(t time.Time) (string, error) { 50 newUlid, err := ulid.New(ulid.Timestamp(t), rand.Reader) 51 if err != nil { 52 return "", err 53 } 54 return newUlid.String(), nil 55 } 56 57 // NewRandomULID returns a new ULID string using a random time in an ~80 year range around the current datetime, or an error if something goes wrong. 58 func NewRandomULID() (string, error) { 59 b1, err := rand.Int(rand.Reader, big.NewInt(randomRange)) 60 if err != nil { 61 return "", err 62 } 63 r1 := time.Duration(int(b1.Int64())) 64 65 b2, err := rand.Int(rand.Reader, big.NewInt(randomRange)) 66 if err != nil { 67 return "", err 68 } 69 r2 := -time.Duration(int(b2.Int64())) 70 71 arbitraryTime := time.Now().Add(r1 * time.Second).Add(r2 * time.Second) 72 newUlid, err := ulid.New(ulid.Timestamp(arbitraryTime), rand.Reader) 73 if err != nil { 74 return "", err 75 } 76 return newUlid.String(), nil 77 }