Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ go get github.com/goglue/rulesengine
| DateBetween | Date / Time | Checks is a time is between a given range. |
| WithinLast | Date / Time | Checks is a time is within the last X of a given duration. |
| WithinNext | Date / Time | Checks is a time is within the next X a given duration. |
| YearEq | Date / Time | Checks is a time is in a given year. |
| MonthEq | Date / Time | Checks is a time is in a given month. |
| Any | Array | Returns `true` if any element statisfy the given rule. |
| All | Array | Returns `true` if all elements satisfy the given rule. |
| None | Array | Returns `true` if no elements satisfy the given rule. |
Expand Down
20 changes: 20 additions & 0 deletions helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,26 @@ func isWithinTime(val any, duration any, op Operator) (bool, error) {
return false, nil
}

func compareTimePart(actual any, expected any, op Operator) (bool, error) {
t, ok := actual.(time.Time)
if !ok {
return false, newError(errType, actual)
}
value, err := toFloat(expected)
if err != nil {
return false, err
}
target := int(value)

switch op {
case YearEq:
return t.Year() == target, nil
case MonthEq:
return int(t.Month()) == target, nil
}
return false, nil
}

func resolveExpectedTime(expected any, now time.Time) (time.Time, error) {
switch v := expected.(type) {
case time.Time:
Expand Down
2 changes: 2 additions & 0 deletions operators.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ const (
DateBetween Operator = "DATE_BETWEEN"
WithinLast Operator = "WITHIN_LAST"
WithinNext Operator = "WITHIN_NEXT"
YearEq Operator = "YEAR_EQ"
MonthEq Operator = "MONTH_EQ"

// Arrays
Any Operator = "ANY"
Expand Down
6 changes: 6 additions & 0 deletions rulesengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ func evaluateRule(operator Operator, actual, expected any) (bool, error) {
}
return true, nil

case YearEq, MonthEq:
if res, err := compareTimePart(actual, expected, operator); !res || err != nil {
return res, err
}
return true, nil

// ---------- Null / Existence ----------
case IsNull, NotExists:
if actual != nil {
Expand Down
21 changes: 21 additions & 0 deletions rulesengine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,27 @@ var (
inputData: map[string]any{"startDate": relativeTime},
expResult: RuleResult{Result: true},
},
{
ruleNodes: Rule{
Operator: YearEq, Field: "startDate", Value: relativeNow.Year(),
},
inputData: map[string]any{"startDate": relativeTime},
expResult: RuleResult{Result: true},
},
{
ruleNodes: Rule{
Operator: YearEq, Field: "startDate", Value: 2020,
},
inputData: map[string]any{"startDate": relativeTime},
expResult: RuleResult{Result: false},
},
{
ruleNodes: Rule{
Operator: MonthEq, Field: "startDate", Value: int(time.June),
},
inputData: map[string]any{"startDate": relativeTime},
expResult: RuleResult{Result: true},
},
{
ruleNodes: Rule{
Operator: WithinLast, Field: "startDate", Value: last10Sec,
Expand Down