From 99f69112220c0177be0355d5cbfcff908ccedb0f Mon Sep 17 00:00:00 2001 From: john Date: Wed, 11 Jul 2018 13:51:03 +0800 Subject: [PATCH 1/4] =?UTF-8?q?gtime=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=A0=BC=E5=BC=8F=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/os/gtime/gtime.go | 30 ++-- g/os/gtime/gtime_format.go | 127 +++++++++++++++++ g/os/gtime/gtime_time.go | 129 ++++++++++++++++++ geg/os/gtime/gtime_format.go | 20 +++ .../gtime/{gtime2.go => gtime_strtotime.go} | 0 geg/other/test.go | 8 +- 6 files changed, 294 insertions(+), 20 deletions(-) create mode 100644 g/os/gtime/gtime_format.go create mode 100644 g/os/gtime/gtime_time.go create mode 100644 geg/os/gtime/gtime_format.go rename geg/os/gtime/{gtime2.go => gtime_strtotime.go} (100%) diff --git a/g/os/gtime/gtime.go b/g/os/gtime/gtime.go index 2b72b0827..385ad0e2f 100644 --- a/g/os/gtime/gtime.go +++ b/g/os/gtime/gtime.go @@ -81,19 +81,8 @@ func Datetime() string { return time.Now().Format("2006-01-02 15:04:05") } -// 时间戳转换为指定格式的字符串,format格式形如:2006-01-02 03:04:05 PM -// 第二个参数指定需要格式化的时间戳,为非必需参数,默认为当前时间戳 -func Format(format string, timestamps...int64) string { - timestamp := Second() - if len(timestamps) > 0 { - timestamp = timestamps[0] - } - return time.Unix(timestamp, 0).Format(format) -} - -// 字符串转换为时间对象,需要给定字符串时间格式,format格式形如:2006-01-02 15:04:05 -// 不传递自定义格式下默认支持的标准时间格式: -// "2017-12-14 04:51:34 +0805 LMT", +// 字符串转换为时间对象,可以指定字符串时间格式,format格式形如:Y-m-d H:i:s。 +// 不传递自定义格式时,默认支持的标准时间格式: // "2006-01-02T15:04:05Z07:00", // "2014-01-17T01:19:15+08:00", // "2018-02-09T20:46:17.897Z", @@ -104,11 +93,7 @@ func Format(format string, timestamps...int64) string { func StrToTime(str string, format...string) (time.Time, error) { // 优先使用用户输入日期格式进行转换 if len(format) > 0 { - if t, err := time.ParseInLocation(format[0], str, time.Local); err == nil { - return t, nil - } else { - return time.Time{}, err - } + return StrToTimeLayout(str, formatToStdLayout(format[0])) } var result time.Time var local = time.Local @@ -188,3 +173,12 @@ func StrToTime(str string, format...string) (time.Time, error) { } return result, errors.New("unsupported time format") } + +// 通过标准库layout模板解析字符串 +func StrToTimeLayout(str string, layout string) (time.Time, error) { + if t, err := time.ParseInLocation(layout, str, time.Local); err == nil { + return t, nil + } else { + return time.Time{}, err + } +} diff --git a/g/os/gtime/gtime_format.go b/g/os/gtime/gtime_format.go new file mode 100644 index 000000000..f47533160 --- /dev/null +++ b/g/os/gtime/gtime_format.go @@ -0,0 +1,127 @@ +// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +package gtime + +import ( + "strings" +) + +var ( + // 参考:http://php.net/manual/zh/function.date.php + formats = map[byte]string { + // ================== 日 ================== + 'd' : "02", // 月份中的第几天,有前导零的 2 位数字(01 到 31) + 'D' : "Mon", // 星期中的第几天,文本表示,3 个字母(Mon 到 Sun) + 'j' : "=j=02", // 月份中的第几天,没有前导零(1 到 31) + 'l' : "Monday", // ("L"的小写字母)星期几,完整的文本格式(Sunday 到 Saturday) + + // ================== 月 ================== + 'F' : "January", // 月份,完整的文本格式,例如 January 或者 March January 到 December + 'm' : "01", // 数字表示的月份,有前导零(01 到 12) + 'M' : "Jan", // 三个字母缩写表示的月份(Jan 到 Dec) + 'n' : "1", // 数字表示的月份,没有前导零(1 到 12) + + // ================== 年 ================== + 'Y' : "2006", // 4 位数字完整表示的年份, 例如:1999 或 2003 + 'y' : "06", // 2 位数字表示的年份, 例如:99 或 03 + + // ================== 时间 ================== + 'a' : "pm", // 小写的上午和下午值 am 或 pm + 'A' : "PM", // 大写的上午和下午值 AM 或 PM + 'g' : "3", // 小时,12 小时格式,没有前导零, 1 到 12 + 'G' : "=G=15", // 小时,24 小时格式,没有前导零, 0 到 23 + 'h' : "03", // 小时,12 小时格式,有前导零, 01 到 12 + 'H' : "15", // 小时,24 小时格式,有前导零, 00 到 23 + 'i' : "04", // 有前导零的分钟数, 00 到 59 + 's' : "05", // 秒数,有前导零, 00 到 59 + 'u' : "=u=.000", // 毫秒(3位) + + // ================== 时区 ================== + 'e' : "MST", // 时区标识, 例如:UTC,GMT,CST + 'O' : "-0700", // 与UTC相差的小时数, 例如:+0200 + 'P' : "-07:00", // 与UTC的差别,小时和分钟之间有冒号分隔, 例如:+02:00 + } +) + +// 将自定义的格式转换为标准库时间格式 +func formatToStdLayout(format string) string { + s := "" + for i := 0; i < len(format); { + switch format[i] { + case '\\': + if i < len(format)-1 { + s += string(format[i+1]) + i += 2 + continue + } else { + return s + } + + default: + if f, ok := formats[format[i]]; ok { + switch format[i] { + case 'j': + s += "02" + case 'G': + s += "15" + case 'u': + if i > 0 && format[i - 1] == '.' { + s += "000" + } else { + s += ".000" + } + default: + s += f + } + } else { + s += f + } + } + } + return s +} + +// 格式化,使用自定义日期格式 +func (t *Time) Format(format string) string { + s := "" + for i := 0; i < len(format); { + switch format[i] { + case '\\': + if i < len(format) - 1 { + s += string(format[i + 1]) + i += 2 + continue + } else { + return s + } + + default: + if f, ok := formats[format[i]]; ok { + r := t.Time.Format(f) + switch format[i] { + case 'j': + s += strings.Replace(r, "=j=0", "", -1) + case 'G': + s += strings.Replace(r, "=G=0", "", -1) + case 'u': + s += strings.Replace(r, "=u=.", "", -1) + default: + s += r + } + } else { + s += f + } + } + i++ + } + return s +} + +// 格式化,使用标准库格式 +func (t *Time) Layout(layout string) string { + return t.Time.Format(layout) +} \ No newline at end of file diff --git a/g/os/gtime/gtime_time.go b/g/os/gtime/gtime_time.go new file mode 100644 index 000000000..b900dd10d --- /dev/null +++ b/g/os/gtime/gtime_time.go @@ -0,0 +1,129 @@ +// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://gitee.com/johng/gf. + +package gtime + +import "time" + +type Time struct { + time.Time +} + +// 创建一个空的时间对象,参数可以是标准库时间对象,可选 +func New (t...time.Time) *Time { + if len(t) > 0 { + return NewFromTime(t[0]) + } + return &Time{ + time.Time{}, + } +} + +// 当前时间对象 +func Now() *Time { + return &Time{ + time.Now(), + } +} + +// 标准时间对象转换为自定义的时间对象 +func NewFromTime (t time.Time) *Time { + return &Time{ + t, + } +} + +// 从字符串转换为时间对象,复杂的时间字符串需要给定格式 +func NewFromStr (str string, format...string) *Time { + if t, err := StrToTime(str, format...); err == nil { + return &Time{ + t, + } + } + return nil +} + +// 时间戳转换为时间对象 +func NewFromTimeStamp (timestamp int64) *Time { + return &Time{ + time.Unix(timestamp, 0), + } +} + +// 秒数 +func (t *Time) Second() int64 { + return t.UnixNano()/1e9 +} + +// 纳秒数 +func (t *Time) Nanosecond() int64 { + return t.UnixNano() +} + +// 微秒数 +func (t *Time) Microsecond() int64 { + return t.UnixNano()/1e3 +} + +// 毫秒数 +func (t *Time) Millisecond() int64 { + return t.UnixNano()/1e6 +} + +// 转换为字符串 +func (t *Time) String() string { + return t.Format("Y-m-d H:i:s") +} + +// 转换为标准库日期对象 +func (t *Time) ToTime() time.Time { + return t.Time +} + +// 复制当前时间对象 +func (t *Time) Clone() *Time { + return New(t.Time) +} + +// 当前时间加上指定时间段 +func (t *Time) Add(d time.Duration) { + t.Time = t.Time.Add(d) +} + +// 时区转换为指定的时区 +func (t *Time) ToLocation(location *time.Location) { + t.Time = t.Time.In(location) +} + +// 时区转换为UTC时区 +func (t *Time) UTC() { + t.Time = t.Time.UTC() +} + +// 时区转换为当前设定的Local时区 +func (t *Time) Local() { + t.Time = t.Time.Local() +} + +// 时间日期计算 +func (t *Time) AddDate(years int, months int, days int) { + t.Time = t.Time.AddDate(years, months, days) +} + +// Round将舍入t的结果返回到d的最接近的倍数(从零时间开始)。 +// 中间值的舍入行为是向上舍入。 如果d <= 0,Round返回t剥离任何单调时钟读数但不改变。 +// Round作为零时间以来的绝对持续时间运行; 它不适用于当时的演示形式。 +// 因此,Round(Hour)可能会返回非零分钟的时间,具体取决于时间的位置。 +func (t *Time) Round(d time.Duration) { + t.Time = t.Time.Round(d) +} + +// Truncate将舍入t的结果返回到d的倍数(从零时间开始)。 如果d <= 0,则Truncate返回t剥离任何单调时钟读数但不改变。 +// 截断时间作为零时间以来的绝对持续时间运行; 它不适用于当时的演示形式。 +// 因此,截断(小时)可能会返回非零分钟的时间,具体取决于时间的位置。 +func (t *Time) Truncate(d time.Duration) { + t.Time = t.Time.Truncate(d) +} \ No newline at end of file diff --git a/geg/os/gtime/gtime_format.go b/geg/os/gtime/gtime_format.go new file mode 100644 index 000000000..abef37f9e --- /dev/null +++ b/geg/os/gtime/gtime_format.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + "gitee.com/johng/gf/g/os/gtime" +) + +func main() { + formats := []string{ + "Y-m-d H:i:s", + "2006-01-02T15:04:05Z07:00", + "2006-01-02T15:04:05.999999999Z07:00", + } + t := gtime.Now() + for _, f := range formats { + fmt.Println(f) + fmt.Println(t.Format(f)) + fmt.Println() + } +} diff --git a/geg/os/gtime/gtime2.go b/geg/os/gtime/gtime_strtotime.go similarity index 100% rename from geg/os/gtime/gtime2.go rename to geg/os/gtime/gtime_strtotime.go diff --git a/geg/other/test.go b/geg/other/test.go index dff028ff9..cbfd08f05 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,10 +1,14 @@ package main import ( - "gitee.com/johng/gf/g/util/gregx" "fmt" + "time" ) func main() { - fmt.Println(gregx.MatchString(`[-/]`, "-")) + //t, err := gtime.StrToTime("2018-01-02 13:08:01") + //fmt.Println(err) + //fmt.Println(t.Format("3:4")) + //fmt.Println(time.Now().Format(".000")) + fmt.Println(time.Now().Format(".000")) } From 5860b5efd08cee78e3c3e2ef8785cc1c9528d2c4 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 11 Jul 2018 17:06:47 +0800 Subject: [PATCH 2/4] =?UTF-8?q?gregx=E5=8C=85=E5=90=8D=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=B8=BAgregex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/encoding/gxml/gxml.go | 4 +-- g/g.go | 4 +-- g/net/ghttp/ghttp_request.go | 6 ++-- g/net/ghttp/ghttp_server_hooks.go | 6 ++-- g/net/ghttp/ghttp_server_router.go | 10 +++--- g/net/gipv4/gipv4.go | 4 +-- g/net/gipv6/gipv6.go | 4 +-- g/os/gfile/gfile.go | 4 +-- g/os/glog/glog_logger.go | 4 +-- g/os/gtime/gtime.go | 16 +++++----- g/os/gtime/gtime_time.go | 24 ++++++++++++-- g/util/{gregx/gregx.go => gregex/gregex.go} | 2 +- .../gregx_test.go => gregex/gregex_test.go} | 2 +- g/util/gvalid/gvalid.go | 32 +++++++++---------- geg/os/gtime/{gtime1.go => gtime_regex.go} | 3 +- 15 files changed, 73 insertions(+), 52 deletions(-) rename g/util/{gregx/gregx.go => gregex/gregex.go} (99%) rename g/util/{gregx/gregx_test.go => gregex/gregex_test.go} (98%) rename geg/os/gtime/{gtime1.go => gtime_regex.go} (81%) diff --git a/g/encoding/gxml/gxml.go b/g/encoding/gxml/gxml.go index c262eef77..52c651ccb 100644 --- a/g/encoding/gxml/gxml.go +++ b/g/encoding/gxml/gxml.go @@ -11,7 +11,7 @@ import ( "github.com/clbanning/mxj" "encoding/xml" "io" - "gitee.com/johng/gf/g/util/gregx" + "gitee.com/johng/gf/g/util/gregex" "github.com/axgle/mahonia" "errors" "fmt" @@ -57,7 +57,7 @@ func prepare(xmlbyte []byte) error { return reader.NewDecoder().NewReader(input), nil } - matchStr, err := gregx.MatchString(patten, string(xmlbyte)) + matchStr, err := gregex.MatchString(patten, string(xmlbyte)) if err != nil { return err } diff --git a/g/g.go b/g/g.go index b2cd29f55..aacde4597 100644 --- a/g/g.go +++ b/g/g.go @@ -19,7 +19,7 @@ import ( "gitee.com/johng/gf/g/net/ghttp" "gitee.com/johng/gf/g/net/gtcp" "gitee.com/johng/gf/g/net/gudp" - "gitee.com/johng/gf/g/util/gregx" + "gitee.com/johng/gf/g/util/gregex" ) const ( @@ -140,7 +140,7 @@ func Redis(name...string) *gredis.Redis { if m := config.GetMap("redis"); m != nil { // host:port[,db[,pass]] if v, ok := m[group]; ok { - array, err := gregx.MatchString(`(.+):(\d+),{0,1}(\d*),{0,1}(.*)`, gconv.String(v)) + array, err := gregex.MatchString(`(.+):(\d+),{0,1}(\d*),{0,1}(.*)`, gconv.String(v)) if err == nil { return gredis.New(gredis.Config{ Host : array[1], diff --git a/g/net/ghttp/ghttp_request.go b/g/net/ghttp/ghttp_request.go index 0d301da9c..d5cf37a48 100644 --- a/g/net/ghttp/ghttp_request.go +++ b/g/net/ghttp/ghttp_request.go @@ -12,7 +12,7 @@ import ( "gitee.com/johng/gf/g/util/gconv" "gitee.com/johng/gf/g/encoding/gjson" "gitee.com/johng/gf/g/container/gtype" - "gitee.com/johng/gf/g/util/gregx" + "gitee.com/johng/gf/g/util/gregex" "gitee.com/johng/gf/g/os/gtime" ) @@ -320,7 +320,7 @@ func (r *Request) IsExited() bool { func (r *Request) GetHost() string { host := r.parsedHost.Val() if len(host) == 0 { - array, _ := gregx.MatchString(`(.+):(\d+)`, r.Host) + array, _ := gregex.MatchString(`(.+):(\d+)`, r.Host) if len(array) > 1 { host = array[1] } else { @@ -335,7 +335,7 @@ func (r *Request) GetHost() string { func (r *Request) GetClientIp() string { ip := r.clientIp.Val() if len(ip) == 0 { - array, _ := gregx.MatchString(`(.+):(\d+)`, r.RemoteAddr) + array, _ := gregex.MatchString(`(.+):(\d+)`, r.RemoteAddr) if len(array) > 1 { ip = array[1] } else { diff --git a/g/net/ghttp/ghttp_server_hooks.go b/g/net/ghttp/ghttp_server_hooks.go index a4f6856ab..d4ee82617 100644 --- a/g/net/ghttp/ghttp_server_hooks.go +++ b/g/net/ghttp/ghttp_server_hooks.go @@ -11,7 +11,7 @@ import ( "errors" "strings" "container/list" - "gitee.com/johng/gf/g/util/gregx" + "gitee.com/johng/gf/g/util/gregex" ) // hook缓存项,根据URL.Path进行缓存,因此对象中带有缓存参数 @@ -164,11 +164,11 @@ func (s *Server) searchHookHandler(r *Request, hook string) []*hookCacheItem { item := e.Value.(*HandlerItem) if strings.EqualFold(item.router.Method, gDEFAULT_METHOD) || strings.EqualFold(item.router.Method, r.Method) { regrule, names := s.patternToRegRule(item.router.Uri) - if gregx.IsMatchString(regrule, r.URL.Path) { + if gregex.IsMatchString(regrule, r.URL.Path) { hookItem := &hookCacheItem {item.faddr, nil} // 如果需要query匹配,那么需要重新解析URL if len(names) > 0 { - if match, err := gregx.MatchString(regrule, r.URL.Path); err == nil { + if match, err := gregex.MatchString(regrule, r.URL.Path); err == nil { array := strings.Split(names, ",") if len(match) > len(array) { hookItem.values = make(map[string][]string) diff --git a/g/net/ghttp/ghttp_server_router.go b/g/net/ghttp/ghttp_server_router.go index 32aa01acb..4307bd88c 100644 --- a/g/net/ghttp/ghttp_server_router.go +++ b/g/net/ghttp/ghttp_server_router.go @@ -11,7 +11,7 @@ import ( "errors" "strings" "container/list" - "gitee.com/johng/gf/g/util/gregx" + "gitee.com/johng/gf/g/util/gregex" ) // handler缓存项,根据URL.Path进行缓存,因此对象中带有缓存参数 @@ -52,11 +52,11 @@ func (s *Server)parsePattern(pattern string) (domain, method, uri string, err er uri = pattern domain = gDEFAULT_DOMAIN method = gDEFAULT_METHOD - if array, err := gregx.MatchString(`([a-zA-Z]+):(.+)`, pattern); len(array) > 1 && err == nil { + if array, err := gregex.MatchString(`([a-zA-Z]+):(.+)`, pattern); len(array) > 1 && err == nil { method = array[1] uri = array[2] } - if array, err := gregx.MatchString(`(.+)@([\w\.\-]+)`, uri); len(array) > 1 && err == nil { + if array, err := gregex.MatchString(`(.+)@([\w\.\-]+)`, uri); len(array) > 1 && err == nil { uri = array[1] domain = array[2] } @@ -229,11 +229,11 @@ func (s *Server) searchHandlerDynamic(r *Request) *handlerCacheItem { item := e.Value.(*HandlerItem) if strings.EqualFold(item.router.Method, gDEFAULT_METHOD) || strings.EqualFold(item.router.Method, r.Method) { rule, names := s.patternToRegRule(item.router.Uri) - if gregx.IsMatchString(rule, r.URL.Path) { + if gregex.IsMatchString(rule, r.URL.Path) { handlerItem := &handlerCacheItem{item, nil} // 如果需要query匹配,那么需要重新解析URL if len(names) > 0 { - if match, err := gregx.MatchString(rule, r.URL.Path); err == nil { + if match, err := gregex.MatchString(rule, r.URL.Path); err == nil { array := strings.Split(names, ",") if len(match) > len(array) { handlerItem.values = make(map[string][]string) diff --git a/g/net/gipv4/gipv4.go b/g/net/gipv4/gipv4.go index eed98fa89..93bb405ae 100644 --- a/g/net/gipv4/gipv4.go +++ b/g/net/gipv4/gipv4.go @@ -14,12 +14,12 @@ import ( "strings" "regexp" "fmt" - "gitee.com/johng/gf/g/util/gregx" + "gitee.com/johng/gf/g/util/gregex" ) // 判断所给地址是否是一个IPv4地址 func Validate(ip string) bool { - return gregx.IsMatchString(`^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$`, ip) + return gregex.IsMatchString(`^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$`, ip) } // ip字符串转为整形 diff --git a/g/net/gipv6/gipv6.go b/g/net/gipv6/gipv6.go index d22edd496..97f342bd7 100644 --- a/g/net/gipv6/gipv6.go +++ b/g/net/gipv6/gipv6.go @@ -7,10 +7,10 @@ // IPv6 package gipv6 -import "gitee.com/johng/gf/g/util/gregx" +import "gitee.com/johng/gf/g/util/gregex" // 判断所给地址是否是一个IPv6地址 func Validate(ip string) bool { - return gregx.IsMatchString(`^([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}$|^:((:[\da-fA-F]{1,4}){1,6}|:)$|^[\da-fA-F]{1,4}:((:[\da-fA-F]{1,4}){1,5}|:)$|^([\da-fA-F]{1,4}:){2}((:[\da-fA-F]{1,4}){1,4}|:)$|^([\da-fA-F]{1,4}:){3}((:[\da-fA-F]{1,4}){1,3}|:)$|^([\da-fA-F]{1,4}:){4}((:[\da-fA-F]{1,4}){1,2}|:)$|^([\da-fA-F]{1,4}:){5}:([\da-fA-F]{1,4})?$|^([\da-fA-F]{1,4}:){6}:$`, ip) + return gregex.IsMatchString(`^([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}$|^:((:[\da-fA-F]{1,4}){1,6}|:)$|^[\da-fA-F]{1,4}:((:[\da-fA-F]{1,4}){1,5}|:)$|^([\da-fA-F]{1,4}:){2}((:[\da-fA-F]{1,4}){1,4}|:)$|^([\da-fA-F]{1,4}:){3}((:[\da-fA-F]{1,4}){1,3}|:)$|^([\da-fA-F]{1,4}:){4}((:[\da-fA-F]{1,4}){1,2}|:)$|^([\da-fA-F]{1,4}:){5}:([\da-fA-F]{1,4})?$|^([\da-fA-F]{1,4}:){6}:$`, ip) } diff --git a/g/os/gfile/gfile.go b/g/os/gfile/gfile.go index bc295bd3d..757b23a6b 100644 --- a/g/os/gfile/gfile.go +++ b/g/os/gfile/gfile.go @@ -21,7 +21,7 @@ import ( "os/user" "runtime" "path/filepath" - "gitee.com/johng/gf/g/util/gregx" + "gitee.com/johng/gf/g/util/gregex" "gitee.com/johng/gf/g/container/gtype" ) @@ -480,7 +480,7 @@ func MainPkgPath() string { if strings.EqualFold("", file) { // 如果是通过init包方法进入,那么无法得到准确的文件路径 f = "" - } else if !gregx.IsMatchString("^" + GoRootOfBuild(), file) { + } else if !gregex.IsMatchString("^" + GoRootOfBuild(), file) { // 不包含go源码路径 f = file } diff --git a/g/os/glog/glog_logger.go b/g/os/glog/glog_logger.go index 5117b04f7..33a8487ef 100644 --- a/g/os/glog/glog_logger.go +++ b/g/os/glog/glog_logger.go @@ -16,7 +16,7 @@ import ( "runtime" "strconv" "gitee.com/johng/gf/g/os/gfile" - "gitee.com/johng/gf/g/util/gregx" + "gitee.com/johng/gf/g/util/gregex" "gitee.com/johng/gf/g/os/gfilepool" ) @@ -146,7 +146,7 @@ func (l *Logger) backtrace() string { for i := 1; i < 10000; i++ { if _, cfile, cline, ok := runtime.Caller(i + l.btSkip.Val()); ok { // 不打印出go源码路径 - if !gregx.IsMatchString("^" + gfile.GoRootOfBuild(), cfile) { + if !gregex.IsMatchString("^" + gfile.GoRootOfBuild(), cfile) { backtrace += strconv.Itoa(index) + ". " + cfile + ":" + strconv.Itoa(cline) + ln index++ } diff --git a/g/os/gtime/gtime.go b/g/os/gtime/gtime.go index 385ad0e2f..c92ffa371 100644 --- a/g/os/gtime/gtime.go +++ b/g/os/gtime/gtime.go @@ -81,8 +81,8 @@ func Datetime() string { return time.Now().Format("2006-01-02 15:04:05") } -// 字符串转换为时间对象,可以指定字符串时间格式,format格式形如:Y-m-d H:i:s。 -// 不传递自定义格式时,默认支持的标准时间格式: +// 字符串转换为时间对象,支持的标准时间格式: +// "2017-12-14 04:51:34 +0805 LMT", // "2006-01-02T15:04:05Z07:00", // "2014-01-17T01:19:15+08:00", // "2018-02-09T20:46:17.897Z", @@ -90,11 +90,7 @@ func Datetime() string { // "2018-02-09T20:46:17Z", // "2018-02-09 20:46:17", // "2018-02-09", -func StrToTime(str string, format...string) (time.Time, error) { - // 优先使用用户输入日期格式进行转换 - if len(format) > 0 { - return StrToTimeLayout(str, formatToStdLayout(format[0])) - } +func StrToTime(str string) (time.Time, error) { var result time.Time var local = time.Local if match := timeRegex.FindStringSubmatch(str); len(match) > 0 { @@ -174,7 +170,11 @@ func StrToTime(str string, format...string) (time.Time, error) { return result, errors.New("unsupported time format") } -// 通过标准库layout模板解析字符串 +// 字符串转换为时间对象,指定字符串时间格式,format格式形如:Y-m-d H:i:s +func StrToTimeFormat(str string, format string) (time.Time, error) { + return StrToTimeLayout(str, formatToStdLayout(format)) +} +// 字符串转换为时间对象,通过标准库layout格式进行解析,layout格式形如:2006-01-02 15:04:05 func StrToTimeLayout(str string, layout string) (time.Time, error) { if t, err := time.ParseInLocation(layout, str, time.Local); err == nil { return t, nil diff --git a/g/os/gtime/gtime_time.go b/g/os/gtime/gtime_time.go index b900dd10d..f11f0d77f 100644 --- a/g/os/gtime/gtime_time.go +++ b/g/os/gtime/gtime_time.go @@ -37,8 +37,28 @@ func NewFromTime (t time.Time) *Time { } // 从字符串转换为时间对象,复杂的时间字符串需要给定格式 -func NewFromStr (str string, format...string) *Time { - if t, err := StrToTime(str, format...); err == nil { +func NewFromStr (str string) *Time { + if t, err := StrToTime(str); err == nil { + return &Time{ + t, + } + } + return nil +} + +// 从字符串转换为时间对象,指定字符串时间格式,format格式形如:Y-m-d H:i:s +func NewFromStrFormat (str string, format string) *Time { + if t, err := StrToTimeFormat(str, format); err == nil { + return &Time{ + t, + } + } + return nil +} + +// 从字符串转换为时间对象,通过标准库layout格式进行解析,layout格式形如:2006-01-02 15:04:05 +func NewFromStrLayout (str string, layout string) *Time { + if t, err := StrToTimeLayout(str, layout); err == nil { return &Time{ t, } diff --git a/g/util/gregx/gregx.go b/g/util/gregex/gregex.go similarity index 99% rename from g/util/gregx/gregx.go rename to g/util/gregex/gregex.go index e96cea8c6..fc11206c3 100644 --- a/g/util/gregx/gregx.go +++ b/g/util/gregex/gregex.go @@ -5,7 +5,7 @@ // You can obtain one at https://gitee.com/johng/gf. // 正则表达式. -package gregx +package gregex import ( "regexp" diff --git a/g/util/gregx/gregx_test.go b/g/util/gregex/gregex_test.go similarity index 98% rename from g/util/gregx/gregx_test.go rename to g/util/gregex/gregex_test.go index d323d2fbb..360694dbd 100644 --- a/g/util/gregx/gregx_test.go +++ b/g/util/gregex/gregex_test.go @@ -6,7 +6,7 @@ // go test *.go -bench=".*" -package gregx +package gregex import ( "testing" diff --git a/g/util/gvalid/gvalid.go b/g/util/gvalid/gvalid.go index aa2344a08..311d4827c 100644 --- a/g/util/gvalid/gvalid.go +++ b/g/util/gvalid/gvalid.go @@ -16,7 +16,7 @@ import ( "gitee.com/johng/gf/g/os/gtime" "gitee.com/johng/gf/g/net/gipv4" "gitee.com/johng/gf/g/net/gipv6" - "gitee.com/johng/gf/g/util/gregx" + "gitee.com/johng/gf/g/util/gregex" "gitee.com/johng/gf/g/util/gconv" "gitee.com/johng/gf/g/encoding/gjson" "gitee.com/johng/gf/g/container/gmap" @@ -493,12 +493,12 @@ func Check(val interface{}, rules string, msgs interface{}, params...map[string] // 需要判断是否被|符号截断,如果是,那么需要进行整合 for i := index + 1; i < len(items); i++ { // 判断下一个规则是否合法,不合法那么和当前正则规则进行整合 - if !gregx.IsMatchString(gSINGLE_RULE_PATTERN, items[i]) { + if !gregex.IsMatchString(gSINGLE_RULE_PATTERN, items[i]) { ruleVal += "|" + items[i] index++ } } - match = gregx.IsMatchString(ruleVal, value) + match = gregex.IsMatchString(ruleVal, value) // 日期格式, case "date": @@ -560,19 +560,19 @@ func Check(val interface{}, rules string, msgs interface{}, params...map[string] * 虚拟运营商:170、173 */ case "phone": - match = gregx.IsMatchString(`^13[\d]{9}$|^14[5,7]{1}\d{8}$|^15[^4]{1}\d{8}$|^17[0,3,5,6,7,8]{1}\d{8}$|^18[\d]{9}$`, value) + match = gregex.IsMatchString(`^13[\d]{9}$|^14[5,7]{1}\d{8}$|^15[^4]{1}\d{8}$|^17[0,3,5,6,7,8]{1}\d{8}$|^18[\d]{9}$`, value) // 国内座机电话号码:"XXXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"、"XXXXXXXX" case "telephone": - match = gregx.IsMatchString(`^((\d{3,4})|\d{3,4}-)?\d{7,8}$`, value) + match = gregex.IsMatchString(`^((\d{3,4})|\d{3,4}-)?\d{7,8}$`, value) // 腾讯QQ号,从10000开始 case "qq": - match = gregx.IsMatchString(`^[1-9][0-9]{4,}$`, value) + match = gregex.IsMatchString(`^[1-9][0-9]{4,}$`, value) // 中国邮政编码 case "postcode": - match = gregx.IsMatchString(`^[1-9]\d{5}$`, value) + match = gregex.IsMatchString(`^[1-9]\d{5}$`, value) /* 公民身份证号 @@ -596,25 +596,25 @@ func Check(val interface{}, rules string, msgs interface{}, params...map[string] (^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$) */ case "id-number": - match = gregx.IsMatchString(`(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$)`, value) + match = gregex.IsMatchString(`(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$)`, value) // 通用帐号规则(字母开头,只能包含字母、数字和下划线,长度在6~18之间) case "passport": - match = gregx.IsMatchString(`^[a-zA-Z]{1}\w{5,17}$`, value) + match = gregex.IsMatchString(`^[a-zA-Z]{1}\w{5,17}$`, value) // 通用密码(任意可见字符,长度在6~18之间) case "password": - match = gregx.IsMatchString(`^[\w\S]{6,18}$`, value) + match = gregex.IsMatchString(`^[\w\S]{6,18}$`, value) // 中等强度密码(在弱密码的基础上,必须包含大小写字母和数字) case "password2": - if gregx.IsMatchString(`^[\w\S]{6,18}$`, value) && gregx.IsMatchString(`[a-z]+`, value) && gregx.IsMatchString(`[A-Z]+`, value) && gregx.IsMatchString(`\d+`, value) { + if gregex.IsMatchString(`^[\w\S]{6,18}$`, value) && gregex.IsMatchString(`[a-z]+`, value) && gregex.IsMatchString(`[A-Z]+`, value) && gregex.IsMatchString(`\d+`, value) { match = true } // 强等强度密码(在弱密码的基础上,必须包含大小写字母、数字和特殊字符) case "password3": - if gregx.IsMatchString(`^[\w\S]{6,18}$`, value) && gregx.IsMatchString(`[a-z]+`, value) && gregx.IsMatchString(`[A-Z]+`, value) && gregx.IsMatchString(`\d+`, value) && gregx.IsMatchString(`\S+`, value) { + if gregex.IsMatchString(`^[\w\S]{6,18}$`, value) && gregex.IsMatchString(`[a-z]+`, value) && gregex.IsMatchString(`[A-Z]+`, value) && gregex.IsMatchString(`\d+`, value) && gregex.IsMatchString(`\S+`, value) { match = true } @@ -644,15 +644,15 @@ func Check(val interface{}, rules string, msgs interface{}, params...map[string] // 邮件 case "email": - match = gregx.IsMatchString(`^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$`, value) + match = gregex.IsMatchString(`^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$`, value) // URL case "url": - match = gregx.IsMatchString(`^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$`, value) + match = gregex.IsMatchString(`^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$`, value) // domain case "domain": - match = gregx.IsMatchString(`^([0-9a-zA-Z][0-9a-zA-Z-]{0,62}\.)+([0-9a-zA-Z][0-9a-zA-Z-]{0,62})\.?$`, value) + match = gregex.IsMatchString(`^([0-9a-zA-Z][0-9a-zA-Z-]{0,62}\.)+([0-9a-zA-Z][0-9a-zA-Z-]{0,62})\.?$`, value) // IP(IPv4/IPv6) case "ip": @@ -668,7 +668,7 @@ func Check(val interface{}, rules string, msgs interface{}, params...map[string] // MAC地址 case "mac": - match = gregx.IsMatchString(`^([0-9A-Fa-f]{2}-){5}[0-9A-Fa-f]{2}$`, value) + match = gregex.IsMatchString(`^([0-9A-Fa-f]{2}-){5}[0-9A-Fa-f]{2}$`, value) default: errorMsgs[ruleKey] = "Invalid rule name:" + ruleKey diff --git a/geg/os/gtime/gtime1.go b/geg/os/gtime/gtime_regex.go similarity index 81% rename from geg/os/gtime/gtime1.go rename to geg/os/gtime/gtime_regex.go index f4ba82bd0..b34af30f0 100644 --- a/geg/os/gtime/gtime1.go +++ b/geg/os/gtime/gtime_regex.go @@ -3,10 +3,11 @@ package main import ( "regexp" "fmt" + "gitee.com/johng/gf/g/os/gtime" ) func main() { - timeRegex, err := regexp.Compile(`(\d{4}-\d{2}-\d{2})[\sT]{0,1}(\d{2}:\d{2}:\d{2}){0,1}\.{0,1}(\d{0,9})([\sZ]{0,1})([\+-]{0,1})([:\d]*)`) + timeRegex, err := regexp.Compile(gtime.TIME_REAGEX_PATTERN) if err != nil { panic(err) } From c933a1515e37882984326111aff6390c338328cf Mon Sep 17 00:00:00 2001 From: John Date: Wed, 11 Jul 2018 17:41:39 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E5=AE=8C=E6=88=90gtime=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E6=97=B6=E9=97=B4=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/os/gtime/gtime_format.go | 2 +- geg/os/gtime/gtime_format.go | 9 ++++++--- geg/os/gtime/gtime_layout.go | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 geg/os/gtime/gtime_layout.go diff --git a/g/os/gtime/gtime_format.go b/g/os/gtime/gtime_format.go index f47533160..d2185737a 100644 --- a/g/os/gtime/gtime_format.go +++ b/g/os/gtime/gtime_format.go @@ -113,7 +113,7 @@ func (t *Time) Format(format string) string { s += r } } else { - s += f + s += string(format[i]) } } i++ diff --git a/geg/os/gtime/gtime_format.go b/geg/os/gtime/gtime_format.go index abef37f9e..6791929dd 100644 --- a/geg/os/gtime/gtime_format.go +++ b/geg/os/gtime/gtime_format.go @@ -7,9 +7,12 @@ import ( func main() { formats := []string{ - "Y-m-d H:i:s", - "2006-01-02T15:04:05Z07:00", - "2006-01-02T15:04:05.999999999Z07:00", + "Y-m-d H:i:s.u", + "D M d H:i:s e O Y", + // 可以使用转义字符转移有意义的格式字母 + "T\\i\\m\\e \\i\\s: h:i:s a", + // format格式不支持标准库格式混合,相互隔离 + "2006-01-02T15:04:05.000000000Z07:00", } t := gtime.Now() for _, f := range formats { diff --git a/geg/os/gtime/gtime_layout.go b/geg/os/gtime/gtime_layout.go new file mode 100644 index 000000000..055e83026 --- /dev/null +++ b/geg/os/gtime/gtime_layout.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "gitee.com/johng/gf/g/os/gtime" +) + +func main() { + formats := []string{ + "2006-01-02 15:04:05.000", + "Mon Jan _2 15:04:05 MST 2006", + "Time is: 03:04:05 PM", + "2006-01-02T15:04:05.000000000Z07:00 MST", + } + t := gtime.Now() + for _, f := range formats { + fmt.Println(f) + fmt.Println(t.Layout(f)) + fmt.Println() + } +} From 0cb88ac146f096def54a5904e0f8c03a06a0021a Mon Sep 17 00:00:00 2001 From: John Date: Wed, 11 Jul 2018 17:59:16 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E5=AE=8C=E6=88=90gtime=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E6=97=B6=E9=97=B4=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E5=8A=9F=E8=83=BD=E7=A4=BA=E4=BE=8B=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=8F=8A=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/os/gtime/gtime_format.go | 7 ++++++- g/os/gtime/gtime_time.go | 2 +- geg/os/gtime/gtime_format.go | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/g/os/gtime/gtime_format.go b/g/os/gtime/gtime_format.go index d2185737a..97d45255f 100644 --- a/g/os/gtime/gtime_format.go +++ b/g/os/gtime/gtime_format.go @@ -41,9 +41,13 @@ var ( 'u' : "=u=.000", // 毫秒(3位) // ================== 时区 ================== - 'e' : "MST", // 时区标识, 例如:UTC,GMT,CST 'O' : "-0700", // 与UTC相差的小时数, 例如:+0200 'P' : "-07:00", // 与UTC的差别,小时和分钟之间有冒号分隔, 例如:+02:00 + 'T' : "MST", // 时区缩写, 例如:UTC,GMT,CST + + // ================== 完整的日期/时间 ================== + 'c' : "2006-01-02T15:04:05-07:00", // ISO 8601 格式的日期,例如:2004-02-12T15:19:21+00:00 + 'r' : "Mon, 02 Jan 06 15:04 MST", // RFC 822 格式的日期,例如:Thu, 21 Dec 2000 16:01:07 +0200 } ) @@ -74,6 +78,7 @@ func formatToStdLayout(format string) string { } else { s += ".000" } + default: s += f } diff --git a/g/os/gtime/gtime_time.go b/g/os/gtime/gtime_time.go index f11f0d77f..2862f7561 100644 --- a/g/os/gtime/gtime_time.go +++ b/g/os/gtime/gtime_time.go @@ -73,7 +73,7 @@ func NewFromTimeStamp (timestamp int64) *Time { } } -// 秒数 +// 秒数(时间戳) func (t *Time) Second() int64 { return t.UnixNano()/1e9 } diff --git a/geg/os/gtime/gtime_format.go b/geg/os/gtime/gtime_format.go index 6791929dd..33c726d61 100644 --- a/geg/os/gtime/gtime_format.go +++ b/geg/os/gtime/gtime_format.go @@ -8,9 +8,9 @@ import ( func main() { formats := []string{ "Y-m-d H:i:s.u", - "D M d H:i:s e O Y", + "D M d H:i:s T O Y", // 可以使用转义字符转移有意义的格式字母 - "T\\i\\m\\e \\i\\s: h:i:s a", + "\\T\\i\\m\\e \\i\\s: h:i:s a", // format格式不支持标准库格式混合,相互隔离 "2006-01-02T15:04:05.000000000Z07:00", }