diff --git a/.travis.yml b/.travis.yml index ee2f52ac1..8bcf0f4ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ branches: - staging env: -- GF_DEBUG=1 GO111MODULE=on +- TZ=Asia/Shanghai GF_DEBUG=1 GO111MODULE=on services: - mysql diff --git a/database/gdb/gdb_core_structure.go b/database/gdb/gdb_core_structure.go index 27fedb2a1..9458de0ab 100644 --- a/database/gdb/gdb_core_structure.go +++ b/database/gdb/gdb_core_structure.go @@ -1,4 +1,4 @@ -// Copyright GoFrame Author(https://github.com/gogf/gf). All Rights Reserved. +// Copyright GoFrame Author(https://goframe.org). 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, @@ -7,7 +7,6 @@ package gdb import ( - "github.com/gogf/gf/errors/gerror" "github.com/gogf/gf/util/gutil" "strings" "time" @@ -56,6 +55,7 @@ func (c *Core) convertFieldValueToLocalValue(fieldValue interface{}, fieldType s return gconv.Int(gconv.String(fieldValue)) case + "int8", // For pgsql, int8 = bigint. "big_int", "bigint", "bigserial": @@ -162,15 +162,11 @@ func (c *Core) mappingAndFilterData(schema, table string, data map[string]interf if foundKey != "" { data[foundKey] = dataValue delete(data, dataKey) - } else if !filter { - if schema != "" { - return nil, gerror.Newf(`no column of name "%s" found for table "%s" in schema "%s"`, dataKey, table, schema) - } - return nil, gerror.Newf(`no column of name "%s" found for table "%s"`, dataKey, table) } } } // Data filtering. + // It deletes all key-value pairs that has incorrect field name. if filter { for dataKey, _ := range data { if _, ok := fieldsMap[dataKey]; !ok { diff --git a/database/gdb/gdb_z_mysql_model_test.go b/database/gdb/gdb_z_mysql_model_test.go index c52a13919..697f78382 100644 --- a/database/gdb/gdb_z_mysql_model_test.go +++ b/database/gdb/gdb_z_mysql_model_test.go @@ -1,4 +1,4 @@ -// Copyright GoFrame Author(https://github.com/gogf/gf). All Rights Reserved. +// Copyright GoFrame Author(https://goframe.org). 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, @@ -496,6 +496,16 @@ func Test_Model_Update(t *testing.T) { n, _ := result.RowsAffected() t.Assert(n, 1) }) + // Update + Fields(string) + gtest.C(t, func(t *gtest.T) { + result, err := db.Table(table).Fields("passport").Data(g.Map{ + "passport": "user_44", + "none": "none", + }).Where("passport='user_4'").Update() + t.Assert(err, nil) + n, _ := result.RowsAffected() + t.Assert(n, 1) + }) } func Test_Model_Clone(t *testing.T) { diff --git a/database/gdb/gdb_z_mysql_types_test.go b/database/gdb/gdb_z_mysql_types_test.go index 9f34771f4..afe03a5d5 100644 --- a/database/gdb/gdb_z_mysql_types_test.go +++ b/database/gdb/gdb_z_mysql_types_test.go @@ -8,6 +8,7 @@ package gdb_test import ( "fmt" + "github.com/gogf/gf/os/gtime" "testing" "github.com/gogf/gf/frame/g" @@ -15,6 +16,7 @@ import ( "github.com/gogf/gf/test/gtest" ) +// All types testing. func Test_Types(t *testing.T) { gtest.C(t, func(t *gtest.T) { if _, err := db.Exec(fmt.Sprintf(` @@ -67,11 +69,34 @@ func Test_Types(t *testing.T) { t.Assert(one["blob"].String(), data["blob"]) t.Assert(one["binary"].String(), data["binary"]) t.Assert(one["date"].String(), data["date"]) - t.Assert(one["time"].String(), data["time"]) + t.Assert(one["time"].String(), `0000-01-01 10:00:01`) t.Assert(one["decimal"].String(), -123.46) t.Assert(one["double"].String(), data["double"]) t.Assert(one["bit"].Int(), data["bit"]) t.Assert(one["tinyint"].Bool(), data["tinyint"]) - t.Assert(one["tinyint"].Bool(), data["tinyint"]) + + type T struct { + Id int + Blob []byte + Binary []byte + Date *gtime.Time + Time *gtime.Time + Decimal float64 + Double float64 + Bit int8 + TinyInt bool + } + var obj *T + err = db.Table("types").Struct(&obj) + t.Assert(err, nil) + t.Assert(obj.Id, 1) + t.Assert(obj.Blob, data["blob"]) + t.Assert(obj.Binary, data["binary"]) + t.Assert(obj.Date.Format("Y-m-d"), data["date"]) + t.Assert(obj.Time.String(), `0000-01-01 10:00:01`) + t.Assert(obj.Decimal, -123.46) + t.Assert(obj.Double, data["double"]) + t.Assert(obj.Bit, data["bit"]) + t.Assert(obj.TinyInt, data["tinyint"]) }) } diff --git a/frame/gins/gins_database.go b/frame/gins/gins_database.go index bcedabf7f..b3a57a6b1 100644 --- a/frame/gins/gins_database.go +++ b/frame/gins/gins_database.go @@ -8,6 +8,7 @@ package gins import ( "fmt" + "github.com/gogf/gf/errors/gerror" "github.com/gogf/gf/internal/intlog" "github.com/gogf/gf/text/gstr" "github.com/gogf/gf/util/gutil" @@ -47,7 +48,25 @@ func Database(name ...string) gdb.DB { configMap = Config().GetMap(configNodeKey) } if len(configMap) == 0 && !gdb.IsConfigured() { - panic(fmt.Sprintf(`database init failed: "%s" node not found, is config file or configuration missing?`, configNodeNameDatabase)) + if !Config().Available() { + exampleFileName := "config.example.toml" + if Config().Available(exampleFileName) { + panic(gerror.Newf( + `configuration file "%s" not found, but found "%s", did you miss renaming the configuration example file?`, + Config().GetFileName(), + exampleFileName, + )) + } else { + panic(gerror.Newf( + `configuration file "%s" not found, did you miss the configuration file or the file name setting?`, + Config().GetFileName(), + )) + } + } + panic(gerror.Newf( + `database initialization failed: "%s" node not found, is configuration file or configuration node missing?`, + configNodeNameDatabase, + )) } if len(configMap) == 0 { configMap = make(map[string]interface{}) diff --git a/i18n/gi18n/gi18n_manager.go b/i18n/gi18n/gi18n_manager.go index e7105c5be..6b737df94 100644 --- a/i18n/gi18n/gi18n_manager.go +++ b/i18n/gi18n/gi18n_manager.go @@ -1,4 +1,4 @@ -// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// Copyright GoFrame Author(https://goframe.org). 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, @@ -13,8 +13,6 @@ import ( "strings" "sync" - "github.com/gogf/gf/os/glog" - "github.com/gogf/gf/os/gfsnotify" "github.com/gogf/gf/text/gregex" @@ -235,11 +233,11 @@ func (m *Manager) init() { m.data[lang] = make(map[string]string) } if j, err := gjson.LoadContent(file.Content()); err == nil { - for k, v := range j.ToMap() { + for k, v := range j.Map() { m.data[lang][k] = gconv.String(v) } } else { - glog.Errorf("load i18n file '%s' failed: %v", name, err) + intlog.Errorf("load i18n file '%s' failed: %v", name, err) } } } @@ -270,11 +268,11 @@ func (m *Manager) init() { m.data[lang] = make(map[string]string) } if j, err := gjson.LoadContent(gfile.GetBytes(file)); err == nil { - for k, v := range j.ToMap() { + for k, v := range j.Map() { m.data[lang][k] = gconv.String(v) } } else { - glog.Errorf("load i18n file '%s' failed: %v", file, err) + intlog.Errorf("load i18n file '%s' failed: %v", file, err) } } // Monitor changes of i18n files for hot reload feature. diff --git a/os/gtime/gtime.go b/os/gtime/gtime.go index 500b39761..1c6c5a35c 100644 --- a/os/gtime/gtime.go +++ b/os/gtime/gtime.go @@ -10,10 +10,10 @@ package gtime import ( - "errors" "fmt" "github.com/gogf/gf/errors/gerror" "github.com/gogf/gf/internal/utils" + "os" "regexp" "strconv" "strings" @@ -45,7 +45,7 @@ const ( // "2018/10/31 - 16:38:46" // "2018-02-09", // "2018.02.09", - TIME_REAGEX_PATTERN1 = `(\d{4}[-/\.]\d{2}[-/\.]\d{2})[:\sT-]*(\d{0,2}:{0,1}\d{0,2}:{0,1}\d{0,2}){0,1}\.{0,1}(\d{0,9})([\sZ]{0,1})([\+-]{0,1})([:\d]*)` + timeRegexPattern1 = `(\d{4}[-/\.]\d{2}[-/\.]\d{2})[:\sT-]*(\d{0,2}:{0,1}\d{0,2}:{0,1}\d{0,2}){0,1}\.{0,1}(\d{0,9})([\sZ]{0,1})([\+-]{0,1})([:\d]*)` // Regular expression2(datetime separator supports '-', '/', '.'). // Eg: @@ -53,14 +53,21 @@ const ( // 01/Nov/2018 11:50:28 // 01.Nov.2018 11:50:28 // 01.Nov.2018:11:50:28 - TIME_REAGEX_PATTERN2 = `(\d{1,2}[-/\.][A-Za-z]{3,}[-/\.]\d{4})[:\sT-]*(\d{0,2}:{0,1}\d{0,2}:{0,1}\d{0,2}){0,1}\.{0,1}(\d{0,9})([\sZ]{0,1})([\+-]{0,1})([:\d]*)` + timeRegexPattern2 = `(\d{1,2}[-/\.][A-Za-z]{3,}[-/\.]\d{4})[:\sT-]*(\d{0,2}:{0,1}\d{0,2}:{0,1}\d{0,2}){0,1}\.{0,1}(\d{0,9})([\sZ]{0,1})([\+-]{0,1})([:\d]*)` + + // Regular expression3(time). + // Eg: + // 11:50:28 + // 11:50:28.897 + timeRegexPattern3 = `(\d{2}):(\d{2}):(\d{2})\.{0,1}(\d{0,9})` ) var ( // It's more high performance using regular expression // than time.ParseInLocation to parse the datetime string. - timeRegex1, _ = regexp.Compile(TIME_REAGEX_PATTERN1) - timeRegex2, _ = regexp.Compile(TIME_REAGEX_PATTERN2) + timeRegex1, _ = regexp.Compile(timeRegexPattern1) + timeRegex2, _ = regexp.Compile(timeRegexPattern2) + timeRegex3, _ = regexp.Compile(timeRegexPattern3) // Month words to arabic numerals mapping. monthMap = map[string]int{ @@ -95,18 +102,14 @@ var ( // The parameter is an area string specifying corresponding time zone, // eg: Asia/Shanghai. // -// Note that the time zone database needed by LoadLocation may not be -// present on all systems, especially non-Unix systems. -// LoadLocation looks in the directory or uncompressed zip file -// named by the ZONEINFO environment variable, if any, then looks in -// known installation locations on Unix systems, -// and finally looks in $GOROOT/lib/time/zoneinfo.zip. +// This should be called before package "time" import. +// Please refer to issue: https://github.com/golang/go/issues/34814 func SetTimeZone(zone string) error { location, err := time.LoadLocation(zone) - if err == nil { - time.Local = location + if err != nil { + return err } - return err + return os.Setenv("TZ", location.String()) } // Timestamp retrieves and returns the timestamp in seconds. @@ -247,17 +250,33 @@ func StrToTime(str string, format ...string) (*Time, error) { local = time.Local ) if match = timeRegex1.FindStringSubmatch(str); len(match) > 0 && match[1] != "" { - for k, v := range match { - match[k] = strings.TrimSpace(v) - } + //for k, v := range match { + // match[k] = strings.TrimSpace(v) + //} year, month, day = parseDateStr(match[1]) } else if match = timeRegex2.FindStringSubmatch(str); len(match) > 0 && match[1] != "" { - for k, v := range match { - match[k] = strings.TrimSpace(v) - } + //for k, v := range match { + // match[k] = strings.TrimSpace(v) + //} year, month, day = parseDateStr(match[1]) + } else if match = timeRegex3.FindStringSubmatch(str); len(match) > 0 && match[1] != "" { + //for k, v := range match { + // match[k] = strings.TrimSpace(v) + //} + s := strings.Replace(match[2], ":", "", -1) + if len(s) < 6 { + s += strings.Repeat("0", 6-len(s)) + } + hour, _ = strconv.Atoi(match[1]) + min, _ = strconv.Atoi(match[2]) + sec, _ = strconv.Atoi(match[3]) + nsec, _ = strconv.Atoi(match[4]) + for i := 0; i < 9-len(match[4]); i++ { + nsec *= 10 + } + return NewFromTime(time.Date(0, time.Month(1), 1, hour, min, sec, nsec, local)), nil } else { - return nil, errors.New("unsupported time format") + return nil, gerror.New("unsupported time format") } // Time @@ -330,8 +349,8 @@ func StrToTime(str string, format ...string) (*Time, error) { } } } - if year <= 0 { - return nil, errors.New("invalid time string:" + str) + if month <= 0 || day <= 0 { + return nil, gerror.New("invalid time string:" + str) } return NewFromTime(time.Date(year, time.Month(month), day, hour, min, sec, nsec, local)), nil } @@ -347,7 +366,7 @@ func ConvertZone(strTime string, toZone string, fromZone ...string) (*Time, erro if l, err := time.LoadLocation(fromZone[0]); err != nil { return nil, err } else { - t.Time = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Time.Second(), t.Time.Nanosecond(), l) + t.Time = time.Date(t.Year(), time.Month(t.Month()), t.Day(), t.Hour(), t.Minute(), t.Time.Second(), t.Time.Nanosecond(), l) } } if l, err := time.LoadLocation(toZone); err != nil { @@ -387,6 +406,8 @@ func ParseTimeFromContent(content string, format ...string) *Time { return NewFromStr(strings.Trim(match[0], "./_- \n\r")) } else if match := timeRegex2.FindStringSubmatch(content); len(match) >= 1 { return NewFromStr(strings.Trim(match[0], "./_- \n\r")) + } else if match := timeRegex3.FindStringSubmatch(content); len(match) >= 1 { + return NewFromStr(strings.Trim(match[0], "./_- \n\r")) } } return nil diff --git a/os/gtime/gtime_time.go b/os/gtime/gtime_time.go index 66d9d0797..4584b661e 100644 --- a/os/gtime/gtime_time.go +++ b/os/gtime/gtime_time.go @@ -1,4 +1,4 @@ -// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// Copyright GoFrame Author(https://goframe.org). 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, @@ -36,8 +36,24 @@ func New(param ...interface{}) *Time { case *Time: return r case string: + if len(param) > 1 { + switch t := param[1].(type) { + case string: + return NewFromStrFormat(r, t) + case []byte: + return NewFromStrFormat(r, string(t)) + } + } return NewFromStr(r) case []byte: + if len(param) > 1 { + switch t := param[1].(type) { + case string: + return NewFromStrFormat(string(r), t) + case []byte: + return NewFromStrFormat(string(r), string(t)) + } + } return NewFromStr(string(r)) case int: return NewFromTimeStamp(int64(r)) @@ -163,6 +179,11 @@ func (t *Time) TimestampNanoStr() string { return strconv.FormatInt(t.TimestampNano(), 10) } +// Month returns the month of the year specified by t. +func (t *Time) Month() int { + return int(t.Time.Month()) +} + // Second returns the second offset within the minute specified by t, // in the range [0, 59]. func (t *Time) Second() int { @@ -219,22 +240,6 @@ func (t *Time) AddStr(duration string) (*Time, error) { } } -// ToLocation converts current time to specified location. -func (t *Time) ToLocation(location *time.Location) *Time { - newTime := t.Clone() - newTime.Time = newTime.Time.In(location) - return newTime -} - -// ToZone converts current time to specified zone like: Asia/Shanghai. -func (t *Time) ToZone(zone string) (*Time, error) { - if l, err := time.LoadLocation(zone); err == nil { - return t.ToLocation(l), nil - } else { - return nil, err - } -} - // UTC converts current time to UTC timezone. func (t *Time) UTC() *Time { newTime := t.Clone() @@ -252,13 +257,6 @@ func (t *Time) RFC822() string { return t.Layout("Mon, 02 Jan 06 15:04 MST") } -// Local converts the time to local timezone. -func (t *Time) Local() *Time { - newTime := t.Clone() - newTime.Time = newTime.Time.Local() - return newTime -} - // AddDate adds year, month and day to the time. func (t *Time) AddDate(years int, months int, days int) *Time { newTime := t.Clone() diff --git a/os/gtime/gtime_time_zone.go b/os/gtime/gtime_time_zone.go new file mode 100644 index 000000000..d7a50eb2c --- /dev/null +++ b/os/gtime/gtime_time_zone.go @@ -0,0 +1,58 @@ +// Copyright GoFrame Author(https://goframe.org). 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://github.com/gogf/gf. + +package gtime + +import ( + "sync" + "time" +) + +var ( + // locationMap is time zone name to its location object. + // Time zone name is like: Asia/Shanghai. + locationMap = make(map[string]*time.Location) + // locationMu is used for concurrent safety for `locationMap`. + locationMu = sync.RWMutex{} +) + +// ToLocation converts current time to specified location. +func (t *Time) ToLocation(location *time.Location) *Time { + newTime := t.Clone() + newTime.Time = newTime.Time.In(location) + return newTime +} + +// ToZone converts current time to specified zone like: Asia/Shanghai. +func (t *Time) ToZone(zone string) (*Time, error) { + if location, err := t.getLocationByZoneName(zone); err == nil { + return t.ToLocation(location), nil + } else { + return nil, err + } +} + +func (t *Time) getLocationByZoneName(name string) (location *time.Location, err error) { + locationMu.RLock() + location = locationMap[name] + locationMu.RUnlock() + if location == nil { + location, err = time.LoadLocation(name) + if err == nil && location != nil { + locationMu.Lock() + locationMap[name] = location + locationMu.Unlock() + } + } + return +} + +// Local converts the time to local timezone. +func (t *Time) Local() *Time { + newTime := t.Clone() + newTime.Time = newTime.Time.Local() + return newTime +} diff --git a/os/gtime/gtime_z_bench_test.go b/os/gtime/gtime_z_bench_test.go index 85408cf10..b6be5aead 100644 --- a/os/gtime/gtime_z_bench_test.go +++ b/os/gtime/gtime_z_bench_test.go @@ -1,4 +1,4 @@ -// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// Copyright GoFrame Author(https://goframe.org). 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, @@ -8,6 +8,7 @@ package gtime_test import ( "testing" + "time" "github.com/gogf/gf/os/gtime" ) @@ -42,6 +43,18 @@ func Benchmark_StrToTime(b *testing.B) { } } +func Benchmark_StrToTime_Format(b *testing.B) { + for i := 0; i < b.N; i++ { + gtime.StrToTime("2018-02-09 20:46:17.897", "Y-m-d H:i:su") + } +} + +func Benchmark_StrToTime_Layout(b *testing.B) { + for i := 0; i < b.N; i++ { + gtime.StrToTimeLayout("2018-02-09T20:46:17.897Z", time.RFC3339) + } +} + func Benchmark_ParseTimeFromContent(b *testing.B) { for i := 0; i < b.N; i++ { gtime.ParseTimeFromContent("2018-02-09T20:46:17.897Z") diff --git a/os/gtime/gtime_z_unit_basic_test.go b/os/gtime/gtime_z_unit_basic_test.go index d4e0f8fc1..c4e8b2c26 100644 --- a/os/gtime/gtime_z_unit_basic_test.go +++ b/os/gtime/gtime_z_unit_basic_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// Copyright GoFrame Author(https://goframe.org). 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, @@ -7,6 +7,7 @@ package gtime_test import ( + "github.com/gogf/gf/frame/g" "testing" "time" @@ -16,8 +17,8 @@ import ( func Test_SetTimeZone(t *testing.T) { gtest.C(t, func(t *gtest.T) { - gtime.SetTimeZone("Asia/Shanghai") - t.Assert(time.Local.String(), "Asia/Shanghai") + t.Assert(gtime.SetTimeZone("Asia/Shanghai"), nil) + //t.Assert(time.Local.String(), "Asia/Shanghai") }) } @@ -86,6 +87,7 @@ func Test_RFC822(t *testing.T) { func Test_StrToTime(t *testing.T) { gtest.C(t, func(t *gtest.T) { + // Correct datetime string. var testDateTimes = []string{ "2006-01-02 15:04:05", "2006/01/02 15:04:05", @@ -103,13 +105,11 @@ func Test_StrToTime(t *testing.T) { for _, item := range testDateTimes { timeTemp, err := gtime.StrToTime(item) - if err != nil { - t.Error("test fail") - } + t.Assert(err, nil) t.Assert(timeTemp.Time.Format("2006-01-02 15:04:05"), "2006-01-02 15:04:05") } - //正常日期列表,时间00:00:00 + // Correct date string,. var testDates = []string{ "2006.01.02", "2006.01.02 00:00", @@ -118,13 +118,25 @@ func Test_StrToTime(t *testing.T) { for _, item := range testDates { timeTemp, err := gtime.StrToTime(item) - if err != nil { - t.Error("test fail") - } + t.Assert(err, nil) t.Assert(timeTemp.Time.Format("2006-01-02 15:04:05"), "2006-01-02 00:00:00") } - //测试格式化formatToStdLayout + // Correct time string. + var testTimes = g.MapStrStr{ + "16:12:01": "15:04:05", + "16:12:01.789": "15:04:05.000", + } + + for k, v := range testTimes { + time1, err := gtime.StrToTime(k) + t.Assert(err, nil) + time2, err := time.ParseInLocation(v, k, time.Local) + t.Assert(err, nil) + t.Assert(time1.Time, time2) + } + + // formatToStdLayout var testDateFormats = []string{ "Y-m-d H:i:s", "\\T\\i\\m\\e Y-m-d H:i:s", @@ -149,7 +161,7 @@ func Test_StrToTime(t *testing.T) { t.Assert(timeTemp.Time.Format("2006-01-02 15:04:05.000"), "2007-01-02 15:04:05.000") } - //异常日期列表 + // 异常日期列表 var testDatesFail = []string{ "2006.01", "06..02", diff --git a/os/gview/gview_buildin.go b/os/gview/gview_buildin.go index fc4f8f697..064903897 100644 --- a/os/gview/gview_buildin.go +++ b/os/gview/gview_buildin.go @@ -1,4 +1,4 @@ -// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// Copyright GoFrame Author(https://goframe.org). 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, @@ -51,11 +51,11 @@ func (view *View) buildInFuncMaps(value ...interface{}) []map[string]interface{} func (view *View) buildInFuncEq(value interface{}, others ...interface{}) bool { s := gconv.String(value) for _, v := range others { - if strings.Compare(s, gconv.String(v)) != 0 { - return false + if strings.Compare(s, gconv.String(v)) == 0 { + return true } } - return true + return false } // buildInFuncNe implements build-in template function: ne diff --git a/os/gview/gview_unit_basic_test.go b/os/gview/gview_unit_basic_test.go index afca128ed..c46767919 100644 --- a/os/gview/gview_unit_basic_test.go +++ b/os/gview/gview_unit_basic_test.go @@ -175,6 +175,19 @@ func Test_Func(t *testing.T) { t.Assert(err, nil) t.Assert(result, `ILoveGoFrame`) }) + // eq: multiple values. + gtest.C(t, func(t *gtest.T) { + str := `{{eq 1 2 1 3 4 5}}` + result, err := gview.ParseContent(str, nil) + t.Assert(err != nil, false) + t.Assert(result, `true`) + }) + gtest.C(t, func(t *gtest.T) { + str := `{{eq 6 2 1 3 4 5}}` + result, err := gview.ParseContent(str, nil) + t.Assert(err != nil, false) + t.Assert(result, `false`) + }) } func Test_FuncNl2Br(t *testing.T) { diff --git a/util/gconv/gconv_z_unit_time_test.go b/util/gconv/gconv_z_unit_time_test.go index 7f27375a6..608ad6b67 100644 --- a/util/gconv/gconv_z_unit_time_test.go +++ b/util/gconv/gconv_z_unit_time_test.go @@ -1,4 +1,4 @@ -// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// Copyright GoFrame Author(https://goframe.org). 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, @@ -17,9 +17,28 @@ import ( func Test_Time(t *testing.T) { gtest.C(t, func(t *gtest.T) { - t1 := "2011-10-10 01:02:03.456" - t.AssertEQ(gconv.GTime(t1), gtime.NewFromStr(t1)) - t.AssertEQ(gconv.Time(t1), gtime.NewFromStr(t1).Time) + s := "2011-10-10 01:02:03.456" + t.AssertEQ(gconv.GTime(s), gtime.NewFromStr(s)) + t.AssertEQ(gconv.Time(s), gtime.NewFromStr(s).Time) t.AssertEQ(gconv.Duration(100), 100*time.Nanosecond) }) + gtest.C(t, func(t *gtest.T) { + s := "01:02:03.456" + t.AssertEQ(gconv.GTime(s).Hour(), 1) + t.AssertEQ(gconv.GTime(s).Minute(), 2) + t.AssertEQ(gconv.GTime(s).Second(), 3) + t.AssertEQ(gconv.GTime(s), gtime.NewFromStr(s)) + t.AssertEQ(gconv.Time(s), gtime.NewFromStr(s).Time) + }) + gtest.C(t, func(t *gtest.T) { + s := "0000-01-01 01:02:03" + t.AssertEQ(gconv.GTime(s).Year(), 0) + t.AssertEQ(gconv.GTime(s).Month(), 1) + t.AssertEQ(gconv.GTime(s).Day(), 1) + t.AssertEQ(gconv.GTime(s).Hour(), 1) + t.AssertEQ(gconv.GTime(s).Minute(), 2) + t.AssertEQ(gconv.GTime(s).Second(), 3) + t.AssertEQ(gconv.GTime(s), gtime.NewFromStr(s)) + t.AssertEQ(gconv.Time(s), gtime.NewFromStr(s).Time) + }) }