Skip to content

Commit

Permalink
✨ feat(str): add new util func: DatetimeNo(), RandWithTpl() and updat…
Browse files Browse the repository at this point in the history
…e convert to string logic
  • Loading branch information
inhere committed Apr 15, 2023
1 parent 97197ea commit 7f57ef7
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 15 deletions.
3 changes: 1 addition & 2 deletions strutil/convert.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package strutil

import (
"encoding/json"
"errors"
"fmt"
"reflect"
Expand Down Expand Up @@ -171,7 +170,7 @@ func AnyToString(val any, defaultAsErr bool) (str string, err error) {
str = string(value)
case time.Duration:
str = value.String()
case json.Number:
case fmt.Stringer:
str = value.String()
default:
if defaultAsErr {
Expand Down
33 changes: 33 additions & 0 deletions strutil/id.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package strutil

import (
"hash/crc32"
"math/rand"
"os"
"strconv"
"time"

Expand Down Expand Up @@ -33,3 +36,33 @@ func MicroTimeHexID() string {

return strconv.FormatInt(ms, 16) + strconv.FormatInt(int64(ri), 16)
}

// DatetimeNo generate. can use for order-no.
//
// No prefix, return like: 2023041410484904074285478388(len: 28)
func DatetimeNo(prefix string) string {
nt := time.Now()
pl := len(prefix)
bs := make([]byte, 0, 28+pl)
if pl > 0 {
bs = append(bs, prefix...)
}

// micro datatime
bs = nt.AppendFormat(bs, "20060102150405.000000")
bs[14+pl] = '0'

// host
name, err := os.Hostname()
if err != nil {
name = "default"
}
c32 := crc32.ChecksumIEEE([]byte(name)) // eg: 4006367001
bs = strconv.AppendUint(bs, uint64(c32%99), 10)

// rand 10000 - 99999
rand.Seed(nt.UnixNano())
bs = strconv.AppendInt(bs, 10000+rand.Int63n(89999), 10)

return string(bs)
}
21 changes: 17 additions & 4 deletions strutil/id_test.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
package strutil
package strutil_test

import (
"fmt"
"testing"

"github.com/gookit/goutil/strutil"
"github.com/gookit/goutil/testutil/assert"
)

func TestMicroTimeID(t *testing.T) {
for i := 0; i < 10; i++ {
id := MicroTimeID()
fmt.Println(id)
id := strutil.MicroTimeID()
fmt.Println(id, "len:", len(id))
assert.NotEmpty(t, id)
}
}

func TestMicroTimeHexID(t *testing.T) {
for i := 0; i < 10; i++ {
id := MicroTimeHexID()
id := strutil.MicroTimeHexID()
fmt.Println(id, "len:", len(id))
assert.NotEmpty(t, id)
}
}

func TestDatetimeNo(t *testing.T) {
for i := 0; i < 10; i++ {
no := strutil.DatetimeNo("test")
fmt.Println(no, "len:", len(no))
assert.NotEmpty(t, no)
}
}
33 changes: 24 additions & 9 deletions strutil/random.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package strutil

import (
"crypto/rand"
"encoding/base64"
mathRand "math/rand"
"time"

"github.com/gookit/goutil/byteutil"
)

// some consts string chars
const (
Numbers = "0123456789"
HexChars = "0123456789abcdef"
AlphaBet = "abcdefghijklmnopqrstuvwxyz"
AlphaBet1 = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"
AlphaNum = "abcdefghijklmnopqrstuvwxyz0123456789"
AlphaNum2 = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
AlphaNum3 = "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"

Base64Chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/"
)

// RandomChars generate give length random chars at `a-z`
Expand Down Expand Up @@ -58,17 +62,11 @@ func RandomCharsV3(ln int) string {

// RandomBytes generate
func RandomBytes(length int) ([]byte, error) {
b := make([]byte, length)
_, err := rand.Read(b)
// Note that err == nil only if we read len(b) bytes.
if err != nil {
return nil, err
}

return b, nil
return byteutil.Random(length)
}

// RandomString generate.
//
// Example:
//
// // this will give us a 44 byte, base64 encoded output
Expand All @@ -81,3 +79,20 @@ func RandomString(length int) (string, error) {
b, err := RandomBytes(length)
return base64.URLEncoding.EncodeToString(b), err
}

// RandWithTpl generate random string with give template
func RandWithTpl(n int, letters string) string {
if len(letters) == 0 {
letters = AlphaNum2
}

ln := len(letters)
cs := make([]byte, n)
for i := 0; i < n; i++ {
mathRand.Seed(int64(time.Now().Nanosecond()))
idx := mathRand.Intn(ln)
cs[i] = letters[idx]
}

return byteutil.String(cs)
}
3 changes: 3 additions & 0 deletions strutil/random_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,7 @@ func TestRandomString(t *testing.T) {
fmt.Println(s)
assert.NoErr(t, err)
assert.True(t, len(s) > 3)

assert.NotEmpty(t, strutil.RandWithTpl(8, ""))
assert.NotEmpty(t, strutil.RandWithTpl(8, strutil.AlphaBet))
}

0 comments on commit 7f57ef7

Please sign in to comment.