使用govaluate比较日期值的表达式。

huangapple go评论86阅读模式
英文:

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 (
	&quot;github.com/Knetic/govaluate&quot;
	&quot;fmt&quot;
)

func main()  {
	expression, err := govaluate.NewEvaluableExpression(&quot;first_name == &#39;Julian&#39; &amp;&amp; emp_id == 302 &amp;&amp; birth_date &gt;= &#39;2016-12-12&#39; &amp;&amp; birth_date &lt;= &#39;2016-12-25&#39;&quot;)

	parameters := make(map[string]interface{}, 8)
	parameters[&quot;first_name&quot;] = &quot;Julian&quot;
	parameters[&quot;emp_id&quot;] = 302
	parameters[&quot;birth_date&quot;] = &quot;2016-12-15&quot;
	result, err := expression.Evaluate(parameters)

	if err != nil {
		fmt.Println(&quot;Error while evaluating the expression&quot;)
	}

	if result.(bool) {
		fmt.Println(&quot;Condition is evaluated to true&quot;)
	} else {
		fmt.Println(&quot;Condition is evaluated to false&quot;)
	}
}

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(&quot;first_name == &#39;Julian&#39; &amp;&amp; emp_id == 302 &amp;&amp; birth_date &gt;= &#39;2016-12-12&#39; &amp;&amp; birth_date &lt;= &#39;2016-12-25&#39;&quot;)
dateFloat, _ := strconv.ParseFloat(&quot;2016-12-15&quot;, 64)
parameters[&quot;birth_date&quot;] = 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 // &lt;-- 您从请求中获取的 birth_date 字符串

iso8601 := &quot;2006-01-02T15:04:05Z0700&quot;

birthDate, err := time.ParseInLocation(iso8601, birthDateString, 
time.Local)
parameters[&quot;birth_date&quot;] = 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 // &lt;-- the birth_date string you get from the request

iso8601 := &quot;2006-01-02T15:04:05Z0700&quot;

birthDate, err := time.ParseInLocation(iso8601, birthDateString, 
time.Local)
parameters[&quot;birth_date&quot;] = 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 (
	&quot;github.com/Knetic/govaluate&quot;
	&quot;fmt&quot;
	&quot;time&quot;
)

func main()  {
	expression, err := govaluate.NewEvaluableExpression(&quot;first_name == &#39;Julian&#39; &amp;&amp; emp_id == 302 &amp;&amp; birth_date &gt;= &#39;2016-12-15&#39; &amp;&amp; birth_date &lt;= &#39;2016-12-25&#39;&quot;)

	parameters := make(map[string]interface{}, 8)
	parameters[&quot;first_name&quot;] = &quot;Julian&quot;
	parameters[&quot;emp_id&quot;] = 302
	iso8601 := &quot;2006-01-02&quot;
	birthDate, err := time.ParseInLocation(iso8601, &quot;2016-12-15&quot;, time.Local)
	parameters[&quot;birth_date&quot;] = birthDate.Unix()
	result, err := expression.Evaluate(parameters)

	if err != nil {
		fmt.Println(&quot;Error while evaluating the expression&quot;)
	}

	if result.(bool) {
		fmt.Println(&quot;Condition is evaluated to true&quot;)
	} else {
		fmt.Println(&quot;Condition is evaluated to false&quot;)
	}
}

Thank you Library owner and @RayfenWindspear for helping me out on this! Really appreciate!

huangapple
  • 本文由 发表于 2017年7月4日 04:06:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/44893202.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定