add FormatTo/LayoutTo functions for gtime; use custom ExpireFunc to close poool items when pool is close for gpool

This commit is contained in:
John
2019-05-29 11:25:11 +08:00
parent 0a890ad871
commit 7034e2015e
10 changed files with 151 additions and 109 deletions

View File

@ -43,10 +43,11 @@ type ExpireFunc func(interface{})
// New returns a new object pool.
// To ensure execution efficiency, the expiration time cannot be modified once it is set.
// Expire:
//
// Expiration logistics:
// expire = 0 : not expired;
// expire < 0 : immediate recovery after use;
// expire > 0 : timeout recovery;
// expire < 0 : immediate expired after use;
// expire > 0 : timeout expired;
// Note that the expiration time unit is ** milliseconds **.
func New(expire int, newFunc NewFunc, expireFunc...ExpireFunc) *Pool {
r := &Pool {
@ -103,14 +104,26 @@ func (p *Pool) Size() int {
return p.list.Len()
}
// Close closes the pool.
// Close closes the pool. If <p> has ExpireFunc,
// then it automatically closes all items using this function before it's closed.
func (p *Pool) Close() {
p.closed.Set(true)
}
// checkExpire secondly removes expired items from pool.
// checkExpire removes expired items from pool every second.
func (p *Pool) checkExpire() {
if p.closed.Val() {
// If p has ExpireFunc,
// then it must close all items using this function.
if p.ExpireFunc != nil {
for {
if r := p.list.PopFront(); r != nil {
p.ExpireFunc(r.(*poolItem).value)
} else {
break
}
}
}
gtimer.Exit()
}
for {

View File

@ -6,14 +6,15 @@
// go test *.go -bench=".*"
package gpool
package gpool_test
import (
"testing"
"github.com/gogf/gf/g/container/gpool"
"testing"
"sync"
)
var pool = New(99999999, nil)
var pool = gpool.New(99999999, nil)
var syncp = sync.Pool{}
func BenchmarkGPoolPut(b *testing.B) {

View File

@ -75,56 +75,9 @@ var (
dayOfMonth = []int{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}
)
// 自定义的格式转换为标准库时间格式
func formatToStdLayout(format string) string {
b := bytes.NewBuffer(nil)
for i := 0; i < len(format); {
switch format[i] {
case '\\':
if i < len(format)-1 {
b.WriteByte(format[i+1])
i += 2
continue
} else {
return b.String()
}
default:
if f, ok := formats[format[i]]; ok {
// 有几个转换的符号需要特殊处理
switch format[i] {
case 'j': b.WriteString("02")
case 'G': b.WriteString("15")
case 'u':
if i > 0 && format[i-1] == '.' {
b.WriteString("000")
} else {
b.WriteString(".000")
}
default:
b.WriteString(f)
}
} else {
b.WriteByte(format[i])
}
i++
}
}
return b.String()
}
// 将format格式转换为正则表达式规则
func formatToRegexPattern(format string) string {
s := gregex.Quote(formatToStdLayout(format))
s, _ = gregex.ReplaceString(`[0-9]`, `[0-9]`, s)
s, _ = gregex.ReplaceString(`[A-Za-z]`, `[A-Za-z]`, s)
return s
}
// 格式化,使用自定义日期格式
// 使用自定义日期格式格式化输出日期。
func (t *Time) Format(format string) string {
runes := []rune(format)
runes := []rune(format)
buffer := bytes.NewBuffer(nil)
for i := 0; i < len(runes); {
switch runes[i] {
@ -165,14 +118,21 @@ func (t *Time) Format(format string) string {
return buffer.String()
}
// 每月天数后面的英文后缀2 个字符st ndrd 或者 th
func formatMonthDaySuffixMap(day string) string {
switch day {
case "01": return "st"
case "02": return "nd"
case "03": return "rd"
default: return "th"
}
// 通过自定义格式转换当前日期为新的日期。
func (t *Time) FormatTo(format string) *Time {
t.Time = NewFromStr(t.Format(format)).Time
return t
}
// 使用标准库格式格式化输出日期。
func (t *Time) Layout(layout string) string {
return t.Time.Format(layout)
}
// 通过标准库格式转换当前日期为新的日期。
func (t *Time) LayoutTo(layout string) *Time {
t.Time = NewFromStr(t.Layout(layout)).Time
return t
}
// 返回是否是润年
@ -221,7 +181,61 @@ func (t *Time) WeeksOfYear() int {
return week
}
// 格式化使用标准库格式
func (t *Time) Layout(layout string) string {
return t.Time.Format(layout)
// 将自定义的格式转换为标准库时间格式
func formatToStdLayout(format string) string {
b := bytes.NewBuffer(nil)
for i := 0; i < len(format); {
switch format[i] {
case '\\':
if i < len(format)-1 {
b.WriteByte(format[i+1])
i += 2
continue
} else {
return b.String()
}
default:
if f, ok := formats[format[i]]; ok {
// 有几个转换的符号需要特殊处理
switch format[i] {
case 'j': b.WriteString("02")
case 'G': b.WriteString("15")
case 'u':
if i > 0 && format[i-1] == '.' {
b.WriteString("000")
} else {
b.WriteString(".000")
}
default:
b.WriteString(f)
}
} else {
b.WriteByte(format[i])
}
i++
}
}
return b.String()
}
// 将format格式转换为正则表达式规则
func formatToRegexPattern(format string) string {
s := gregex.Quote(formatToStdLayout(format))
s, _ = gregex.ReplaceString(`[0-9]`, `[0-9]`, s)
s, _ = gregex.ReplaceString(`[A-Za-z]`, `[A-Za-z]`, s)
return s
}
// 每月天数后面的英文后缀2 个字符st ndrd 或者 th
func formatMonthDaySuffixMap(day string) string {
switch day {
case "01": return "st"
case "02": return "nd"
case "03": return "rd"
default: return "th"
}
}

View File

@ -13,7 +13,7 @@ type Time struct {
}
// 创建一个空的时间对象,参数可以是标准库时间对象,可选
func New (t...time.Time) *Time {
func New(t...time.Time) *Time {
if len(t) > 0 {
return NewFromTime(t[0])
}
@ -30,14 +30,14 @@ func Now() *Time {
}
// 标准时间对象转换为自定义的时间对象
func NewFromTime (t time.Time) *Time {
func NewFromTime(t time.Time) *Time {
return &Time{
t,
}
}
// 从字符串转换为时间对象,复杂的时间字符串需要给定格式
func NewFromStr (str string) *Time {
func NewFromStr(str string) *Time {
if t, err := StrToTime(str); err == nil {
return t
}
@ -45,7 +45,7 @@ func NewFromStr (str string) *Time {
}
// 从字符串转换为时间对象指定字符串时间格式format格式形如Y-m-d H:i:s
func NewFromStrFormat (str string, format string) *Time {
func NewFromStrFormat(str string, format string) *Time {
if t, err := StrToTimeFormat(str, format); err == nil {
return t
}
@ -53,7 +53,7 @@ func NewFromStrFormat (str string, format string) *Time {
}
// 从字符串转换为时间对象通过标准库layout格式进行解析layout格式形如2006-01-02 15:04:05
func NewFromStrLayout (str string, layout string) *Time {
func NewFromStrLayout(str string, layout string) *Time {
if t, err := StrToTimeLayout(str, layout); err == nil {
return t
}
@ -61,7 +61,7 @@ func NewFromStrLayout (str string, layout string) *Time {
}
// 时间戳转换为时间对象,时间戳支持到纳秒的数值
func NewFromTimeStamp (timestamp int64) *Time {
func NewFromTimeStamp(timestamp int64) *Time {
if timestamp == 0 {
return &Time {}
}
@ -98,7 +98,8 @@ func (t *Time) String() string {
return t.Format("Y-m-d H:i:s")
}
// 转换为标准库日期对象
// Deprecated.
// Directly use t.Time instead.
func (t *Time) ToTime() time.Time {
return t.Time
}
@ -121,13 +122,12 @@ func (t *Time) ToLocation(location *time.Location) *Time {
}
// 时区转换为指定的时区(通过时区名称Asia/Shanghai)
func (t *Time) ToZone(zone string) *Time {
func (t *Time) ToZone(zone string) (*Time, error) {
if l, err := time.LoadLocation(zone); err == nil {
t.Time = t.Time.In(l)
return t
return t, nil
} else {
//panic(err)
return nil
return nil, err
}
}

View File

@ -85,9 +85,24 @@ func Test_Format(t *testing.T) {
})
}
func Test_FormatTo(t *testing.T) {
gtest.Case(t, func() {
timeTemp := gtime.Now()
gtest.Assert(timeTemp.FormatTo("Y-m-01 00:00:01"), timeTemp.Time.Format("2006-01") + "-01 00:00:01")
})
}
func Test_Layout(t *testing.T) {
gtest.Case(t, func() {
timeTemp := gtime.Now()
gtest.Assert(timeTemp.Layout("2006-01-02 15:04:05"), timeTemp.Time.Format("2006-01-02 15:04:05"))
})
}
func Test_LayoutTo(t *testing.T) {
gtest.Case(t, func() {
timeTemp := gtime.Now()
gtest.Assert(timeTemp.LayoutTo("2006-01-02 00:00:00"), timeTemp.Time.Format("2006-01-02 00:00:00"))
})
}

View File

@ -137,7 +137,7 @@ func Test_ToZone(t *testing.T) {
timeTemp.ToLocation(loc)
gtest.Assert(timeTemp.Time.Location().String(), "Asia/Shanghai")
timeTemp1 := timeTemp.ToZone("errZone")
timeTemp1, _ := timeTemp.ToZone("errZone")
if timeTemp1 != nil {
t.Error("test fail")
}

View File

@ -40,10 +40,8 @@ func Struct(params interface{}, pointer interface{}, mapping...map[string]string
}
// Using reflect to do the converting,
// it also supports type of reflect.Value for <pointer>(always in internal usage).
elem := reflect.Value{}
if v, ok := pointer.(reflect.Value); ok {
elem = v
} else {
elem, ok := pointer.(reflect.Value)
if !ok {
rv := reflect.ValueOf(pointer)
if kind := rv.Kind(); kind != reflect.Ptr {
return fmt.Errorf("object pointer should be type of: %v", kind)

View File

@ -0,0 +1,16 @@
package main
import (
"fmt"
"github.com/gogf/gf/g/container/gpool"
"time"
)
func main() {
p := gpool.New(60000, nil, func(i interface{}) {
fmt.Println("expired")
})
p.Put(1)
time.Sleep(10000*time.Second)
fmt.Println(p.Get())
}

View File

@ -1,32 +1,17 @@
package main
import (
"fmt"
"github.com/gogf/gf/g"
"github.com/gogf/gf/g/util/gconv"
"log"
"os"
"github.com/gogf/gf/g/os/glog"
"github.com/gogf/gf/g/os/gtime"
)
func main() {
var mylog = log.New(os.Stdout, "[Api] ", log.LstdFlags|log.Lshortfile)
mylog.Println(123)
return
a := []int{1,2,3}
fmt.Println(a[:0])
return
type Person struct{
Name string
}
type Staff struct{
Person
StaffId int
}
staff := &Staff{}
params := g.Map{
"Name" : "john",
"StaffId" : "10000",
}
gconv.Struct(params, staff)
fmt.Println(staff)
Time := gtime.Now().AddDate(0, -1, 0).Format("Y-m")
glog.Debug(Time)
Time = gtime.Now().AddDate(0, -2, 0).Format("Y-m")
glog.Debug(Time)
Time = gtime.Now().AddDate(0, -3, 0).Format("Y-m")
glog.Debug(Time)
Time = gtime.Now().AddDate(0, -4, 0).Format("Y-m")
glog.Debug(Time)
}