From e4a59a5f03748183659c5cc2ba458ee0e1d813ac Mon Sep 17 00:00:00 2001 From: Vivek Patel Date: Thu, 19 Aug 2021 16:59:19 +0530 Subject: [PATCH] Adds expr functions - modWeek returns modify week part of the date input - random returns random number between range if given - sub returns diff between two dates in milliseconds --- pkg/expr/func_num.go | 33 +++++++++++++++++++++++-- pkg/expr/func_num_test.go | 14 +++++++++++ pkg/expr/func_time.go | 35 +++++++++++++++++++++++++++ pkg/expr/func_time_test.go | 49 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 2 deletions(-) diff --git a/pkg/expr/func_num.go b/pkg/expr/func_num.go index 1d6351e06..63a743d27 100644 --- a/pkg/expr/func_num.go +++ b/pkg/expr/func_num.go @@ -1,9 +1,10 @@ package expr import ( - "math" - "github.com/PaesslerAG/gval" + "github.com/pkg/errors" + "math" + "math/rand" ) func NumericFunctions() []gval.Language { @@ -19,6 +20,7 @@ func NumericFunctions() []gval.Language { gval.Function("sqrt", math.Sqrt), gval.Function("sum", sum), gval.Function("average", average), + gval.Function("random", random), } } @@ -112,3 +114,30 @@ func average(v ...interface{}) float64 { return sum / j } + +func random(v ...float64) (out float64, err error) { + var ( + from, to float64 + totalArgs = len(v) + ) + + if totalArgs == 0 || totalArgs > 2 { + return 0, errors.Errorf("expecting 1 or 2 parameter, got %d", totalArgs) + } + + if totalArgs > 0 { + if to = v[0]; to < 0 { + return 0, errors.New("unexpected input type of 1st parameter") + } + } + + if totalArgs > 1 { + if to = v[1]; to < 0 { + return 0, errors.New("unexpected input type of 2nd parameter") + } + from = v[0] + } + + out = from + rand.Float64()*(to-from) + return +} diff --git a/pkg/expr/func_num_test.go b/pkg/expr/func_num_test.go index fc499a739..feb448694 100644 --- a/pkg/expr/func_num_test.go +++ b/pkg/expr/func_num_test.go @@ -76,3 +76,17 @@ func Example_average() { // output: // 4 } + +func Example_randomWithSingleInput() { + eval(`max(random(6), 7)`, nil) + + // output: + // 7 +} + +func Example_randomWithTwoInput() { + eval(`min(random(2, 6), 1)`, nil) + + // output: + // 1 +} diff --git a/pkg/expr/func_time.go b/pkg/expr/func_time.go index 0d7d975de..84b9877a6 100644 --- a/pkg/expr/func_time.go +++ b/pkg/expr/func_time.go @@ -16,6 +16,7 @@ func TimeFunctions() []gval.Language { gval.Function("parseISOTime", parseISOTime), gval.Function("modTime", modTime), gval.Function("modDate", modDate), + gval.Function("modWeek", modWeek), gval.Function("modMonth", modMonth), gval.Function("modYear", modYear), gval.Function("parseDuration", time.ParseDuration), @@ -23,6 +24,7 @@ func TimeFunctions() []gval.Language { gval.Function("isLeapYear", isLeapYear), gval.Function("now", now), gval.Function("isWeekDay", isWeekDay), + gval.Function("sub", sub), } } @@ -131,6 +133,16 @@ func modDate(base interface{}, mod interface{}) (*time.Time, error) { return &tmp, nil } +func modWeek(base interface{}, mod interface{}) (*time.Time, error) { + t, m, err := prepMod(base, mod) + if err != nil { + return nil, err + } + + tmp := t.AddDate(0, 0, 7*m) + return &tmp, nil +} + func modMonth(base interface{}, mod interface{}) (*time.Time, error) { t, m, err := prepMod(base, mod) if err != nil { @@ -184,3 +196,26 @@ func strfTime(base interface{}, f string) (string, error) { o, _ := strftime.Format(f, *t, strftime.WithMilliseconds('b')) return o, nil } + +// sub returns difference between two date into milliseconds +func sub(from interface{}, to interface{}) (out int64, err error) { + t1, _, err := prepMod(from, 0) + if err != nil { + return + } + + t2, _, err := prepMod(to, 0) + if err != nil { + return + } + + var duration time.Duration + + if t1.After(*t2) { + duration = t1.Sub(*t2) + } else { + return -1, errors.New("expecting 2nd input to be less than 1st input") + } + + return duration.Milliseconds(), nil +} diff --git a/pkg/expr/func_time_test.go b/pkg/expr/func_time_test.go index d13f9ce83..9ccbfbd12 100644 --- a/pkg/expr/func_time_test.go +++ b/pkg/expr/func_time_test.go @@ -85,3 +85,52 @@ func Example_isWeekDay() { // output: // true } + +func Example_modTime() { + eval(`modTime(ghd, "+30m")`, exampleTimeParams) + + // output: + // 1993-02-02 06:30:00 -0500 -0500 +} + +func Example_modWeek() { + eval(`modWeek(ghd, "1")`, exampleTimeParams) + + // output: + // 1993-02-09 06:00:00 -0500 -0500 +} + +func Example_modDate() { + eval(`modDate(ghd, "5")`, exampleTimeParams) + + // output: + // 1993-02-07 06:00:00 -0500 -0500 +} + +func Example_modMonth() { + eval(`modMonth(ghd, "1")`, exampleTimeParams) + + // output: + // 1993-03-02 06:00:00 -0500 -0500 +} + +func Example_modYear() { + eval(`modYear(ghd, "5")`, exampleTimeParams) + + // output: + // 1998-02-02 06:00:00 -0500 -0500 +} + +func Example_sub() { + eval(`sub(hgp, ghd)`, exampleTimeParams) + + // output: + // 321627600000 +} + +func Example_subErrorCheck() { + eval(`sub(ghd, hgp)`, exampleTimeParams) + + // output: + // error: can not evaluate sub(ghd, hgp): expecting 2nd input to be less than 1st input +}