diff --git a/strutil/convert.go b/strutil/convert.go index 9d98f459e..4e0199be7 100644 --- a/strutil/convert.go +++ b/strutil/convert.go @@ -1,7 +1,6 @@ package strutil import ( - "encoding/json" "errors" "fmt" "reflect" @@ -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 { diff --git a/strutil/id.go b/strutil/id.go index 053ba10d7..028264916 100644 --- a/strutil/id.go +++ b/strutil/id.go @@ -1,6 +1,9 @@ package strutil import ( + "hash/crc32" + "math/rand" + "os" "strconv" "time" @@ -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) +} diff --git a/strutil/id_test.go b/strutil/id_test.go index 228d286b4..8a6338a5b 100644 --- a/strutil/id_test.go +++ b/strutil/id_test.go @@ -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) } } diff --git a/strutil/random.go b/strutil/random.go index 562039b27..66aa6a801 100644 --- a/strutil/random.go +++ b/strutil/random.go @@ -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` @@ -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 @@ -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) +} diff --git a/strutil/random_test.go b/strutil/random_test.go index 1e349c7c6..85c108f75 100644 --- a/strutil/random_test.go +++ b/strutil/random_test.go @@ -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)) }