mirror of
https://gitee.com/johng/gf
synced 2026-07-04 21:03:13 +08:00
add FormatTo/LayoutTo functions for gtime; use custom ExpireFunc to close poool items when pool is close for gpool
This commit is contained in:
@ -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 {
|
||||
|
||||
@ -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) {
|
||||
@ -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 nd,rd 或者 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 nd,rd 或者 th
|
||||
func formatMonthDaySuffixMap(day string) string {
|
||||
switch day {
|
||||
case "01": return "st"
|
||||
case "02": return "nd"
|
||||
case "03": return "rd"
|
||||
default: return "th"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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"))
|
||||
})
|
||||
}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
16
geg/container/gpool/gpool_expire.go
Normal file
16
geg/container/gpool/gpool_expire.go
Normal 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())
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user