英文:
Compare date values in expression using govaluate
问题
我正在尝试使用govaluate构建一个规则引擎:https://github.com/Knetic/govaluate
以下是我的代码:
package main
import (
"github.com/Knetic/govaluate"
"fmt"
)
func main() {
expression, err := govaluate.NewEvaluableExpression("first_name == 'Julian' && emp_id == 302 && birth_date >= '2016-12-12' && birth_date <= '2016-12-25'")
parameters := make(map[string]interface{}, 8)
parameters["first_name"] = "Julian"
parameters["emp_id"] = 302
parameters["birth_date"] = "2016-12-15"
result, err := expression.Evaluate(parameters)
if err != nil {
fmt.Println("在评估表达式时发生错误")
}
if result.(bool) {
fmt.Println("条件评估为真")
} else {
fmt.Println("条件评估为假")
}
}
在浏览 govaluate 的类型文档(https://github.com/Knetic/govaluate/blob/master/MANUAL.md)时,我注意到这个语句:"任何可解释为日期的字符串文字(不是参数)将被转换为该日期的 Unix 时间的 float64 表示"
当我执行上面的程序时,我发现结果为 null 的问题:
在评估表达式时发生错误
panic: interface conversion: interface is nil, not bool
我的问题是日期值是否可以作为参数传递?因为我想在运行时比较日期值,所以需要这个功能。
有没有办法实现这个?也许我的使用模式有误。请给予建议。
编辑:
expression, err := govaluate.NewEvaluableExpression("first_name == 'Julian' && emp_id == 302 && birth_date >= '2016-12-12' && birth_date <= '2016-12-25'")
dateFloat, _ := strconv.ParseFloat("2016-12-15", 64)
parameters["birth_date"] = dateFloat
result, err := expression.Evaluate(parameters)
将日期更改为浮点格式并调用 Evaluate 函数。现在条件评估为假。但从逻辑上讲,2016-12-15 在 2016-12-12 和 2016-12-25 之间。表达式应该评估为真。
提前感谢!
英文:
I am trying to build a rule engine using govaluate: https://github.com/Knetic/govaluate
Here is my code:
package main
import (
"github.com/Knetic/govaluate"
"fmt"
)
func main() {
expression, err := govaluate.NewEvaluableExpression("first_name == 'Julian' && emp_id == 302 && birth_date >= '2016-12-12' && birth_date <= '2016-12-25'")
parameters := make(map[string]interface{}, 8)
parameters["first_name"] = "Julian"
parameters["emp_id"] = 302
parameters["birth_date"] = "2016-12-15"
result, err := expression.Evaluate(parameters)
if err != nil {
fmt.Println("Error while evaluating the expression")
}
if result.(bool) {
fmt.Println("Condition is evaluated to true")
} else {
fmt.Println("Condition is evaluated to false")
}
}
While browsing through govaluate Types documentation (https://github.com/Knetic/govaluate/blob/master/MANUAL.md), I noticed this statement "Any string literal (not parameter) which is interpretable as a date will be converted to a float64 representation of that date's unix time."
When i execute the above program, i see an issue with result being null:
Error while evaluating the expression
panic: interface conversion: interface is nil, not bool
My question is whether date value can be passed in as a parameter? As i want to compare date values in runtime, this functionality would be needed.
Is there a way to achieve it? May be my usage pattern is wrong. Please suggest.
Edit:
expression, err := govaluate.NewEvaluableExpression("first_name == 'Julian' && emp_id == 302 && birth_date >= '2016-12-12' && birth_date <= '2016-12-25'")
dateFloat, _ := strconv.ParseFloat("2016-12-15", 64)
parameters["birth_date"] = dateFloat
result, err := expression.Evaluate(parameters)
Changed the date to float format and invoked Evaluate function. Now the condition is evaluated to false. But logically, 2016-12-15 falls between 2016-12-12 and 2016-12-25. The expression should be evaluated to true.
Thanks in advance!
答案1
得分: 2
将您的要求翻译如下:
从相关的 GitHub 问题中转贴我的答案,供未来的搜索者参考;
该库不会尝试将字符串参数解析为日期 - 它期望 birth_date
是该日期的 Unix()
值。这意味着在将其传递给 govaluate 之前,您需要解析日期。
如果您通过 REST API 获取 birth_date
,我建议您确定一种特定的日期格式(例如 ISO8601),并执行以下操作:
var birthDateString string // <-- 您从请求中获取的 birth_date 字符串
iso8601 := "2006-01-02T15:04:05Z0700"
birthDate, err := time.ParseInLocation(iso8601, birthDateString,
time.Local)
parameters["birth_date"] = birthDate.Unix()
英文:
Cross-posting my answer from the associated github issue, for future googlers;
The library doesn't try to parse string parameters as dates - it expects that birth_date
will be the Unix()
value of that date. This means you'll have to parse the date before passing it to govaluate.
If you're getting birth_date
as part of a REST api, I'd suggest settling on one specific date format (such as ISO8601) and doing something like:
var birthDateString string // <-- the birth_date string you get from the request
iso8601 := "2006-01-02T15:04:05Z0700"
birthDate, err := time.ParseInLocation(iso8601, birthDateString,
time.Local)
parameters["birth_date"] = birthDate.Unix()
答案2
得分: 1
以下是工作解决方案:
package main
import (
"github.com/Knetic/govaluate"
"fmt"
"time"
)
func main() {
expression, err := govaluate.NewEvaluableExpression("first_name == 'Julian' && emp_id == 302 && birth_date >= '2016-12-15' && birth_date <= '2016-12-25'")
parameters := make(map[string]interface{}, 8)
parameters["first_name"] = "Julian"
parameters["emp_id"] = 302
iso8601 := "2006-01-02"
birthDate, err := time.ParseInLocation(iso8601, "2016-12-15", time.Local)
parameters["birth_date"] = birthDate.Unix()
result, err := expression.Evaluate(parameters)
if err != nil {
fmt.Println("Error while evaluating the expression")
}
if result.(bool) {
fmt.Println("Condition is evaluated to true")
} else {
fmt.Println("Condition is evaluated to false")
}
}
感谢库的所有者和@RayfenWindspear对我提供帮助!非常感谢!
英文:
Here is the working solution:
package main
import (
"github.com/Knetic/govaluate"
"fmt"
"time"
)
func main() {
expression, err := govaluate.NewEvaluableExpression("first_name == 'Julian' && emp_id == 302 && birth_date >= '2016-12-15' && birth_date <= '2016-12-25'")
parameters := make(map[string]interface{}, 8)
parameters["first_name"] = "Julian"
parameters["emp_id"] = 302
iso8601 := "2006-01-02"
birthDate, err := time.ParseInLocation(iso8601, "2016-12-15", time.Local)
parameters["birth_date"] = birthDate.Unix()
result, err := expression.Evaluate(parameters)
if err != nil {
fmt.Println("Error while evaluating the expression")
}
if result.(bool) {
fmt.Println("Condition is evaluated to true")
} else {
fmt.Println("Condition is evaluated to false")
}
}
Thank you Library owner and @RayfenWindspear for helping me out on this! Really appreciate!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论