From 39f84194ef0192c2dde35611b7b7f0f6f06b99c0 Mon Sep 17 00:00:00 2001 From: jf-tech Date: Fri, 25 Sep 2020 17:52:38 +1200 Subject: [PATCH] move loadLoc to caches --- caches/timeLocCache.go | 22 ++++++++++++++++++++++ caches/timeLocCache_test.go | 28 ++++++++++++++++++++++++++++ times/parse.go | 14 +------------- times/parse_test.go | 32 -------------------------------- times/util.go | 5 +++-- 5 files changed, 54 insertions(+), 47 deletions(-) create mode 100644 caches/timeLocCache.go create mode 100644 caches/timeLocCache_test.go diff --git a/caches/timeLocCache.go b/caches/timeLocCache.go new file mode 100644 index 0000000..a86660f --- /dev/null +++ b/caches/timeLocCache.go @@ -0,0 +1,22 @@ +package caches + +import ( + "time" +) + +// TimeLocationCache is the default loading cache used for caching *time.Location +// object If the default size is too big/small and/or a cache limit isn't desired +// at all, caller can simply replace the cache during global initialization. But +// be aware it's global so any packages uses this package inside your process will +// be affected. +var TimeLocationCache = NewLoadingCache() + +func GetTimeLocation(tz string) (*time.Location, error) { + loc, err := TimeLocationCache.Get(tz, func(key interface{}) (interface{}, error) { + return time.LoadLocation(key.(string)) + }) + if err != nil { + return nil, err + } + return loc.(*time.Location), nil +} diff --git a/caches/timeLocCache_test.go b/caches/timeLocCache_test.go new file mode 100644 index 0000000..39f1ebe --- /dev/null +++ b/caches/timeLocCache_test.go @@ -0,0 +1,28 @@ +package caches + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetTimeLocation(t *testing.T) { + TimeLocationCache = NewLoadingCache() + assert.Equal(t, 0, len(TimeLocationCache.DumpForTest())) + // failure case + expr, err := GetTimeLocation("unknown") + assert.Error(t, err) + assert.Equal(t, "unknown time zone unknown", err.Error()) + assert.Nil(t, expr) + assert.Equal(t, 0, len(TimeLocationCache.DumpForTest())) + // success case + expr, err = GetTimeLocation("America/New_York") + assert.NoError(t, err) + assert.NotNil(t, expr) + assert.Equal(t, 1, len(TimeLocationCache.DumpForTest())) + // repeat success case shouldn't case any cache growth + expr, err = GetTimeLocation("America/New_York") + assert.NoError(t, err) + assert.NotNil(t, expr) + assert.Equal(t, 1, len(TimeLocationCache.DumpForTest())) +} diff --git a/times/parse.go b/times/parse.go index d4a1d5d..7d83833 100644 --- a/times/parse.go +++ b/times/parse.go @@ -8,18 +8,6 @@ import ( "github.com/jf-tech/go-corelib/caches" ) -var locCache = caches.NewLoadingCache() - -func loadLoc(tz string) (*time.Location, error) { - loc, err := locCache.Get(tz, func(key interface{}) (interface{}, error) { - return time.LoadLocation(key.(string)) - }) - if err != nil { - return nil, err - } - return loc.(*time.Location), nil -} - // SmartParse parses a date time string and returns a time.Time and a tz flag indicates whether the // date time string contains tz info. // The date time string can be either date only, or date + time, or date + time + tz. @@ -57,7 +45,7 @@ func SmartParse(s string) (t time.Time, tz bool, err error) { if tzStr, tzFound := probeTimezoneSuffix(s); tzFound { // no err checking because tz from probeTimezoneSuffix guaranteed to be valid. - loc, _ = loadLoc(tzStr) + loc, _ = caches.GetTimeLocation(tzStr) // -1 for the '-' that is not included in tz. s = strings.TrimSpace(s[:len(s)-len(tzStr)-1]) } diff --git a/times/parse_test.go b/times/parse_test.go index f6feaa6..f4cceab 100644 --- a/times/parse_test.go +++ b/times/parse_test.go @@ -7,38 +7,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestLoadLoc(t *testing.T) { - for _, test := range []struct { - tz string - expectedErr string - }{ - { - tz: "America/Los_Angeles", - expectedErr: "", - }, - { - tz: "America/Indiana/Indianapolis", - expectedErr: "", - }, - { - tz: "Unknown", - expectedErr: "unknown time zone Unknown", - }, - } { - t.Run(test.tz, func(t *testing.T) { - loc, err := loadLoc(test.tz) - if test.expectedErr != "" { - assert.Error(t, err) - assert.Equal(t, test.expectedErr, err.Error()) - assert.Nil(t, loc) - } else { - assert.NoError(t, err) - assert.Equal(t, test.tz, loc.String()) - } - }) - } -} - func TestSmartParse_Success(t *testing.T) { for _, test := range []struct { name string diff --git a/times/util.go b/times/util.go index 1e630d2..ac477c6 100644 --- a/times/util.go +++ b/times/util.go @@ -3,6 +3,7 @@ package times import ( "time" + "github.com/jf-tech/go-corelib/caches" "github.com/jf-tech/go-corelib/strs" ) @@ -13,7 +14,7 @@ func OverwriteTZ(t time.Time, tz string) (time.Time, error) { if !strs.IsStrNonBlank(tz) { return t, nil } - loc, err := loadLoc(tz) + loc, err := caches.GetTimeLocation(tz) if err != nil { return time.Time{}, err } @@ -28,7 +29,7 @@ func ConvertTZ(t time.Time, tz string) (time.Time, error) { if !strs.IsStrNonBlank(tz) { return t, nil } - loc, err := loadLoc(tz) + loc, err := caches.GetTimeLocation(tz) if err != nil { return time.Time{}, err }