From 89772555bf0e052eb1674215c0bdbad50fceddaf Mon Sep 17 00:00:00 2001 From: Unknwon Date: Thu, 1 Jan 2015 20:33:52 +0800 Subject: [PATCH] Add time support --- ini.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++------- ini_test.go | 30 ++++++++++++++++++++- 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/ini.go b/ini.go index 40c5bd7..f5dd78c 100644 --- a/ini.go +++ b/ini.go @@ -27,6 +27,7 @@ import ( "strconv" "strings" "sync" + "time" ) const ( @@ -157,6 +158,16 @@ func (k *Key) Int64() (int64, error) { return strconv.ParseInt(k.String(), 10, 64) } +// TimeFormat parses with given format and returns time.Time type value. +func (k *Key) TimeFormat(format string) (time.Time, error) { + return time.Parse(format, k.String()) +} + +// Time parses with RFC3339 format and returns time.Time type value. +func (k *Key) Time() (time.Time, error) { + return k.TimeFormat(time.RFC3339) +} + // MustString returns default value if key value is empty. func (k *Key) MustString(defaultVal string) string { val := k.String() @@ -179,31 +190,47 @@ func (k *Key) MustBool(defaultVal ...bool) bool { // MustFloat64 always returns value without error, // it returns 0.0 if error occurs. func (k *Key) MustFloat64(defaultVal ...float64) float64 { - value, err := k.Float64() + val, err := k.Float64() if len(defaultVal) > 0 && err != nil { return defaultVal[0] } - return value + return val } // MustInt always returns value without error, // it returns 0 if error occurs. func (k *Key) MustInt(defaultVal ...int) int { - value, err := k.Int() + val, err := k.Int() if len(defaultVal) > 0 && err != nil { return defaultVal[0] } - return value + return val } // MustInt64 always returns value without error, // it returns 0 if error occurs. func (k *Key) MustInt64(defaultVal ...int64) int64 { - value, err := k.Int64() + val, err := k.Int64() if len(defaultVal) > 0 && err != nil { return defaultVal[0] } - return value + return val +} + +// MustTimeFormat always parses with given format and returns value without error, +// it returns zero value if error occurs. +func (k *Key) MustTimeFormat(format string, defaultVal ...time.Time) time.Time { + val, err := k.TimeFormat(format) + if len(defaultVal) > 0 && err != nil { + return defaultVal[0] + } + return val +} + +// MustTime always parses with RFC3339 format and returns value without error, +// it returns zero value if error occurs. +func (k *Key) MustTime(defaultVal ...time.Time) time.Time { + return k.MustTimeFormat(time.RFC3339, defaultVal...) } // In always returns value without error, @@ -218,7 +245,7 @@ func (k *Key) In(defaultVal string, candidates []string) string { return defaultVal } -// In always returns value without error, +// InFloat64 always returns value without error, // it returns default value if error occurs or doesn't fit into candidates. func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 { val := k.MustFloat64() @@ -230,7 +257,7 @@ func (k *Key) InFloat64(defaultVal float64, candidates []float64) float64 { return defaultVal } -// In always returns value without error, +// InInt always returns value without error, // it returns default value if error occurs or doesn't fit into candidates. func (k *Key) InInt(defaultVal int, candidates []int) int { val := k.MustInt() @@ -242,7 +269,7 @@ func (k *Key) InInt(defaultVal int, candidates []int) int { return defaultVal } -// In always returns value without error, +// InInt64 always returns value without error, // it returns default value if error occurs or doesn't fit into candidates. func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 { val := k.MustInt64() @@ -254,6 +281,24 @@ func (k *Key) InInt64(defaultVal int64, candidates []int64) int64 { return defaultVal } +// InTimeFormat always parses with given format and returns value without error, +// it returns default value if error occurs or doesn't fit into candidates. +func (k *Key) InTimeFormat(format string, defaultVal time.Time, candidates []time.Time) time.Time { + val := k.MustTimeFormat(format) + for _, cand := range candidates { + if val == cand { + return val + } + } + return defaultVal +} + +// InTime always parses with RFC3339 format and returns value without error, +// it returns default value if error occurs or doesn't fit into candidates. +func (k *Key) InTime(defaultVal time.Time, candidates []time.Time) time.Time { + return k.InTimeFormat(time.RFC3339, defaultVal, candidates) +} + // Strings returns list of string devide by given delimiter. func (k *Key) Strings(delim string) []string { str := k.String() @@ -298,6 +343,21 @@ func (k *Key) Int64s(delim string) []int64 { return vals } +// TimesFormat parses with given format and returns list of time.Time devide by given delimiter. +func (k *Key) TimesFormat(format, delim string) []time.Time { + strs := k.Strings(delim) + vals := make([]time.Time, len(strs)) + for i := range strs { + vals[i], _ = time.Parse(format, strs[i]) + } + return vals +} + +// Times parses with RFC3339 format and returns list of time.Time devide by given delimiter. +func (k *Key) Times(delim string) []time.Time { + return k.TimesFormat(time.RFC3339, delim) +} + // SetValue changes key value. func (k *Key) SetValue(v string) { k.value = v diff --git a/ini_test.go b/ini_test.go index 4bec9bb..a86420d 100644 --- a/ini_test.go +++ b/ini_test.go @@ -18,6 +18,7 @@ import ( "fmt" "strings" "testing" + "time" . "github.com/smartystreets/goconvey/convey" ) @@ -57,11 +58,13 @@ STRING = str BOOL = true FLOAT64 = 1.25 INT = 10 +TIME = 2015-01-01T20:17:05Z [array] STRINGS = en, zh, de FLOAT64S = 1.1, 2.2, 3.3 INTS = 1, 2, 3 +TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z [note] @@ -206,12 +209,19 @@ func Test_Values(t *testing.T) { So(err, ShouldBeNil) So(v4, ShouldEqual, 10) + t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z") + So(err, ShouldBeNil) + v5, err := sec.Key("TIME").Time() + So(err, ShouldBeNil) + So(v5.String(), ShouldEqual, t.String()) + Convey("Must get values with type", func() { So(sec.Key("STRING").MustString("404"), ShouldEqual, "str") So(sec.Key("BOOL").MustBool(), ShouldBeTrue) So(sec.Key("FLOAT64").MustFloat64(), ShouldEqual, 1.25) So(sec.Key("INT").MustInt(), ShouldEqual, 10) So(sec.Key("INT").MustInt64(), ShouldEqual, 10) + So(sec.Key("TIME").MustTime().String(), ShouldEqual, t.String()) Convey("Must get values with default value", func() { So(sec.Key("STRING_404").MustString("404"), ShouldEqual, "404") @@ -219,6 +229,10 @@ func Test_Values(t *testing.T) { So(sec.Key("FLOAT64_404").MustFloat64(2.5), ShouldEqual, 2.5) So(sec.Key("INT_404").MustInt(15), ShouldEqual, 15) So(sec.Key("INT_404").MustInt64(15), ShouldEqual, 15) + + t, err := time.Parse(time.RFC3339, "2014-01-01T20:17:05Z") + So(err, ShouldBeNil) + So(sec.Key("TIME_404").MustTime(t).String(), ShouldEqual, t.String()) }) }) }) @@ -230,11 +244,18 @@ func Test_Values(t *testing.T) { So(sec.Key("INT").InInt(0, []int{10, 20, 30}), ShouldEqual, 10) So(sec.Key("INT").InInt64(0, []int64{10, 20, 30}), ShouldEqual, 10) + zt, err := time.Parse(time.RFC3339, "0001-01-01T01:00:00Z") + So(err, ShouldBeNil) + t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z") + So(err, ShouldBeNil) + So(sec.Key("TIME").InTime(zt, []time.Time{t, time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String()) + Convey("Get value with candidates and default value", func() { So(sec.Key("STRING_404").In("str", []string{"str", "arr", "types"}), ShouldEqual, "str") So(sec.Key("FLOAT64_404").InFloat64(1.25, []float64{1.25, 2.5, 3.75}), ShouldEqual, 1.25) So(sec.Key("INT_404").InInt(10, []int{10, 20, 30}), ShouldEqual, 10) So(sec.Key("INT64_404").InInt64(10, []int64{10, 20, 30}), ShouldEqual, 10) + So(sec.Key("TIME_404").InTime(t, []time.Time{time.Now(), time.Now(), time.Now().Add(1 * time.Second)}).String(), ShouldEqual, t.String()) }) }) @@ -257,6 +278,13 @@ func Test_Values(t *testing.T) { for i, v := range []int64{1, 2, 3} { So(vals3[i], ShouldEqual, v) } + + t, err := time.Parse(time.RFC3339, "2015-01-01T20:17:05Z") + So(err, ShouldBeNil) + vals4 := sec.Key("TIMES").Times(",") + for i, v := range []time.Time{t, t, t} { + So(vals4[i].String(), ShouldEqual, v.String()) + } }) Convey("Get key hash", func() { @@ -270,7 +298,7 @@ func Test_Values(t *testing.T) { }) Convey("Get key strings", func() { - So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,FLOAT64,INT") + So(strings.Join(cfg.Section("types").KeyStrings(), ","), ShouldEqual, "STRING,BOOL,FLOAT64,INT,TIME") }) Convey("Delete a key", func() {