mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-08 06:32:28 +08:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
051f20caef | ||
|
|
613785b07c | ||
|
|
0b0eb695e8 | ||
|
|
745082fff1 | ||
|
|
24b8da360e | ||
|
|
b106c428ae | ||
|
|
8b1171d0cb | ||
|
|
ab012f2545 |
@@ -6,7 +6,7 @@
|
|||||||
<div align="center" style="text-align: center;">
|
<div align="center" style="text-align: center;">
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
[](https://codecov.io/gh/duke-git/lancet)
|
[](https://codecov.io/gh/duke-git/lancet)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<div align="center" style="text-align: center;">
|
<div align="center" style="text-align: center;">
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/duke-git/lancet/releases)
|
[](https://github.com/duke-git/lancet/releases)
|
||||||
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
[](https://pkg.go.dev/github.com/duke-git/lancet)
|
||||||
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
[](https://goreportcard.com/report/github.com/duke-git/lancet)
|
||||||
[](https://codecov.io/gh/duke-git/lancet)
|
[](https://codecov.io/gh/duke-git/lancet)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
package datetime
|
package datetime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -56,24 +56,17 @@ func init() {
|
|||||||
|
|
||||||
// AddMinute add or sub minute to the time
|
// AddMinute add or sub minute to the time
|
||||||
func AddMinute(t time.Time, minute int64) time.Time {
|
func AddMinute(t time.Time, minute int64) time.Time {
|
||||||
s := strconv.FormatInt(minute, 10)
|
return t.Add(time.Minute * time.Duration(minute))
|
||||||
m, _ := time.ParseDuration(s + "m")
|
|
||||||
return t.Add(m)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddHour add or sub hour to the time
|
// AddHour add or sub hour to the time
|
||||||
func AddHour(t time.Time, hour int64) time.Time {
|
func AddHour(t time.Time, hour int64) time.Time {
|
||||||
s := strconv.FormatInt(hour, 10)
|
return t.Add(time.Hour * time.Duration(hour))
|
||||||
h, _ := time.ParseDuration(s + "h")
|
|
||||||
return t.Add(h)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddDay add or sub day to the time
|
// AddDay add or sub day to the time
|
||||||
func AddDay(t time.Time, day int64) time.Time {
|
func AddDay(t time.Time, day int64) time.Time {
|
||||||
dayHours := day * 24
|
return t.Add(24 * time.Hour * time.Duration(day))
|
||||||
d := strconv.FormatInt(dayHours, 10)
|
|
||||||
h, _ := time.ParseDuration(d + "h")
|
|
||||||
return t.Add(h)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNowDate return format yyyy-mm-dd of current date
|
// GetNowDate return format yyyy-mm-dd of current date
|
||||||
@@ -109,7 +102,11 @@ func FormatTimeToStr(t time.Time, format string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FormatStrToTime convert string to time
|
// FormatStrToTime convert string to time
|
||||||
func FormatStrToTime(str, format string) time.Time {
|
func FormatStrToTime(str, format string) (time.Time, error) {
|
||||||
t, _ := time.Parse(timeFormat[format], str)
|
v, ok := timeFormat[format]
|
||||||
return t
|
if !ok {
|
||||||
|
return time.Time{}, fmt.Errorf("format %s not found", format)
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Parse(v, str)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,10 @@ func TestFormatStrToTime(t *testing.T) {
|
|||||||
"2021/01"}
|
"2021/01"}
|
||||||
|
|
||||||
for i := 0; i < len(cases); i++ {
|
for i := 0; i < len(cases); i++ {
|
||||||
res := FormatStrToTime(datetimeStr[i], cases[i])
|
res, err := FormatStrToTime(datetimeStr[i], cases[i])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
expected, _ := time.Parse(formats[i], datetimeStr[i])
|
expected, _ := time.Parse(formats[i], datetimeStr[i])
|
||||||
if res != expected {
|
if res != expected {
|
||||||
utils.LogFailedTestInfo(t, "FormatTimeToStr", cases[i], expected, res)
|
utils.LogFailedTestInfo(t, "FormatTimeToStr", cases[i], expected, res)
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ import (
|
|||||||
|
|
||||||
// After creates a function that invokes func once it's called n or more times
|
// After creates a function that invokes func once it's called n or more times
|
||||||
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
|
func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
|
||||||
|
// Catch programming error while constructing the closure
|
||||||
|
MustBeFunction(fn)
|
||||||
return func(args ...interface{}) []reflect.Value {
|
return func(args ...interface{}) []reflect.Value {
|
||||||
n--
|
n--
|
||||||
if n < 1 {
|
if n < 1 {
|
||||||
return invokeFunc(fn, args...)
|
return unsafeInvokeFunc(fn, args...)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -22,11 +24,12 @@ func After(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
|
|||||||
|
|
||||||
// Before creates a function that invokes func once it's called less than n times
|
// Before creates a function that invokes func once it's called less than n times
|
||||||
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
|
func Before(n int, fn interface{}) func(args ...interface{}) []reflect.Value {
|
||||||
|
// Catch programming error while constructing the closure
|
||||||
|
MustBeFunction(fn)
|
||||||
var res []reflect.Value
|
var res []reflect.Value
|
||||||
|
|
||||||
return func(args ...interface{}) []reflect.Value {
|
return func(args ...interface{}) []reflect.Value {
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
res = invokeFunc(fn, args...)
|
res = unsafeInvokeFunc(fn, args...)
|
||||||
}
|
}
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
fn = nil
|
fn = nil
|
||||||
@@ -69,11 +72,12 @@ func Delay(delay time.Duration, fn interface{}, args ...interface{}) {
|
|||||||
|
|
||||||
// Schedule invoke function every duration time, util close the returned bool chan
|
// Schedule invoke function every duration time, util close the returned bool chan
|
||||||
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool {
|
func Schedule(d time.Duration, fn interface{}, args ...interface{}) chan bool {
|
||||||
|
// Catch programming error while constructing the closure
|
||||||
|
MustBeFunction(fn)
|
||||||
quit := make(chan bool)
|
quit := make(chan bool)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
invokeFunc(fn, args...)
|
unsafeInvokeFunc(fn, args...)
|
||||||
select {
|
select {
|
||||||
case <-time.After(d):
|
case <-time.After(d):
|
||||||
case <-quit:
|
case <-quit:
|
||||||
|
|||||||
@@ -14,6 +14,15 @@ func invokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
|
|||||||
return fv.Call(params)
|
return fv.Call(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unsafeInvokeFunc(fn interface{}, args ...interface{}) []reflect.Value {
|
||||||
|
fv := reflect.ValueOf(fn)
|
||||||
|
params := make([]reflect.Value, len(args))
|
||||||
|
for i, item := range args {
|
||||||
|
params[i] = reflect.ValueOf(item)
|
||||||
|
}
|
||||||
|
return fv.Call(params)
|
||||||
|
}
|
||||||
|
|
||||||
func functionValue(function interface{}) reflect.Value {
|
func functionValue(function interface{}) reflect.Value {
|
||||||
v := reflect.ValueOf(function)
|
v := reflect.ValueOf(function)
|
||||||
if v.Kind() != reflect.Func {
|
if v.Kind() != reflect.Func {
|
||||||
@@ -21,3 +30,10 @@ func functionValue(function interface{}) reflect.Value {
|
|||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MustBeFunction(function interface{}) {
|
||||||
|
v := reflect.ValueOf(function)
|
||||||
|
if v.Kind() != reflect.Func {
|
||||||
|
panic(fmt.Sprintf("Invalid function type, value of type %T", function))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,36 +11,33 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestHttpGet(t *testing.T) {
|
func TestHttpGet(t *testing.T) {
|
||||||
_, e := HttpGet("", nil)
|
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||||
if e == nil {
|
header := map[string]string{
|
||||||
t.FailNow()
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "https://gutendex.com/books?"
|
resp, err := HttpGet(url, header)
|
||||||
queryParams := make(map[string]interface{})
|
|
||||||
queryParams["ids"] = "1"
|
|
||||||
|
|
||||||
resp, err := HttpGet(url, nil, queryParams)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("error: ", err)
|
log.Fatal(err)
|
||||||
//t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
fmt.Println("response: ", resp.StatusCode, string(body))
|
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHttpPost(t *testing.T) {
|
func TestHttpPost(t *testing.T) {
|
||||||
url := "http://api.postcodes.io/postcodes"
|
url := "https://jsonplaceholder.typicode.com/todos"
|
||||||
type Postcode struct {
|
|
||||||
Postcodes []string `json:"postcodes"`
|
|
||||||
}
|
|
||||||
postcode := Postcode{[]string{"OX49 5NU"}}
|
|
||||||
bodyParams, _ := json.Marshal(postcode)
|
|
||||||
header := map[string]string{
|
header := map[string]string{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
|
type Todo struct {
|
||||||
|
UserId int `json:"userId"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
}
|
||||||
|
todo := Todo{1, "TestAddToDo"}
|
||||||
|
bodyParams, _ := json.Marshal(todo)
|
||||||
|
|
||||||
resp, err := HttpPost(url, header, nil, bodyParams)
|
resp, err := HttpPost(url, header, nil, bodyParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -51,34 +48,55 @@ func TestHttpPost(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHttpPut(t *testing.T) {
|
func TestHttpPut(t *testing.T) {
|
||||||
url := "http://public-api-v1.aspirantzhang.com/users/10420"
|
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||||
type User struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
}
|
|
||||||
user := User{
|
|
||||||
"test",
|
|
||||||
"test@test.com",
|
|
||||||
}
|
|
||||||
bodyParams, _ := json.Marshal(user)
|
|
||||||
header := map[string]string{
|
header := map[string]string{
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
}
|
}
|
||||||
|
type Todo struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
UserId int `json:"userId"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
}
|
||||||
|
todo := Todo{1, 1, "TestPutToDo"}
|
||||||
|
bodyParams, _ := json.Marshal(todo)
|
||||||
|
|
||||||
resp, err := HttpPut(url, header, nil, bodyParams)
|
resp, err := HttpPut(url, header, nil, bodyParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("error: ", err)
|
log.Fatal(err)
|
||||||
//t.FailNow()
|
t.FailNow()
|
||||||
|
}
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHttpPatch(t *testing.T) {
|
||||||
|
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||||
|
header := map[string]string{
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
type Todo struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
UserId int `json:"userId"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
}
|
||||||
|
todo := Todo{1, 1, "TestPatchToDo"}
|
||||||
|
bodyParams, _ := json.Marshal(todo)
|
||||||
|
|
||||||
|
resp, err := HttpPatch(url, header, nil, bodyParams)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
t.FailNow()
|
||||||
}
|
}
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
fmt.Println("response: ", resp.StatusCode, string(body))
|
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHttpDelete(t *testing.T) {
|
func TestHttpDelete(t *testing.T) {
|
||||||
url := "http://public-api-v1.aspirantzhang.com/users/10420"
|
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||||
resp, err := HttpDelete(url)
|
resp, err := HttpDelete(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("error: ", err)
|
log.Fatal(err)
|
||||||
//t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
body, _ := ioutil.ReadAll(resp.Body)
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
fmt.Println("response: ", resp.StatusCode, string(body))
|
fmt.Println("response: ", resp.StatusCode, string(body))
|
||||||
@@ -100,25 +118,29 @@ func TestConvertMapToQueryString(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestParseResponse(t *testing.T) {
|
func TestParseResponse(t *testing.T) {
|
||||||
url := "http://public-api-v1.aspirantzhang.com/users"
|
url := "https://jsonplaceholder.typicode.com/todos/1"
|
||||||
type User struct {
|
header := map[string]string{
|
||||||
Id int `json:"id"`
|
"Content-Type": "application/json",
|
||||||
Name string `json:"name"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
}
|
}
|
||||||
type UserResp struct {
|
|
||||||
Data []User `json:"data"`
|
resp, err := HttpGet(url, header)
|
||||||
}
|
|
||||||
resp, err := HttpGet(url)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
userResp := &UserResp{}
|
|
||||||
err = ParseHttpResponse(resp, userResp)
|
type Todo struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
UserId int `json:"userId"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Completed bool `json:"completed"`
|
||||||
|
}
|
||||||
|
|
||||||
|
toDoResp := &Todo{}
|
||||||
|
err = ParseHttpResponse(resp, toDoResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
fmt.Println(userResp.Data)
|
fmt.Println("response: ", toDoResp)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,15 +100,15 @@ func Every(slice, function interface{}) bool {
|
|||||||
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
|
panic("function param should be of type func(int, " + elemType.String() + ")" + reflect.ValueOf(true).Type().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
var indexes []int
|
var currentLength int
|
||||||
for i := 0; i < sv.Len(); i++ {
|
for i := 0; i < sv.Len(); i++ {
|
||||||
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
|
flag := fn.Call([]reflect.Value{reflect.ValueOf(i), sv.Index(i)})[0]
|
||||||
if flag.Bool() {
|
if flag.Bool() {
|
||||||
indexes = append(indexes, i)
|
currentLength++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return len(indexes) == sv.Len()
|
return currentLength == sv.Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some return true if any of the values in the list pass the predicate function.
|
// Some return true if any of the values in the list pass the predicate function.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CamelCase covert string to camelCase string.
|
// CamelCase covert string to camelCase string.
|
||||||
@@ -59,20 +60,10 @@ func LowerFirst(s string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
res := ""
|
r, size := utf8.DecodeRuneInString(s)
|
||||||
for i, v := range []rune(s) {
|
r = unicode.ToLower(r)
|
||||||
if i == 0 {
|
|
||||||
if v >= 65 && v <= 96 {
|
return string(r) + s[size:]
|
||||||
v += 32
|
|
||||||
res += string(v)
|
|
||||||
} else {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res += string(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PadEnd pads string on the right side if it's shorter than size.
|
// PadEnd pads string on the right side if it's shorter than size.
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ func TestLowerFirst(t *testing.T) {
|
|||||||
lowerFirst(t, "foo", "foo")
|
lowerFirst(t, "foo", "foo")
|
||||||
lowerFirst(t, "BAR", "bAR")
|
lowerFirst(t, "BAR", "bAR")
|
||||||
lowerFirst(t, "FOo", "fOo")
|
lowerFirst(t, "FOo", "fOo")
|
||||||
|
lowerFirst(t, "FOo大", "fOo大")
|
||||||
}
|
}
|
||||||
|
|
||||||
func lowerFirst(t *testing.T, test string, expected string) {
|
func lowerFirst(t *testing.T, test string, expected string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user