Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding RFC3339 timestamp support with supported operations: ==, >=, <… #7

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# Folders
_obj
_test
test

# Architecture specific extensions/prefixes
*.[568vq]
Expand Down
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

.PHONY: test


lint:
go fmt ./...
go vet ./...

test:
@mkdir -p test
go test ./... -race -coverprofile=test/coverage.out ./...

12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ Currently only the following operators are supported.
|-|-|-|
|`And`|`&&`||
|`Or`|<code>&#124;&#124;</code>||
|`Equal`, `Eq`|`==`|`string`, `float64`|
|`NotEqual`, `Neq`|`!=`|`string`, `float64`|
|`GreaterThan `, `Gt`|`>`|`string`, `float64`|
|`GreaterThanEqual `, `Gte`|`>=`|`string`, `float64`|
|`LessThan `, `Lt`|`<`|`string`, `float64`|
|`LessThanEqual `, `Lte`|`<=`|`string`, `float64`|
|`Equal`, `Eq`|`==`|`string`, `float64`, `RFC3339 timestamp`|
|`NotEqual`, `Neq`|`!=`|`string`, `float64`, `RFC3339 timestamp`|
|`GreaterThan `, `Gt`|`>`|`string`, `float64`, `RFC3339 timestamp`|
|`GreaterThanEqual `, `Gte`|`>=`|`string`, `float64`, `RFC3339 timestamp`|
|`LessThan `, `Lt`|`<`|`string`, `float64`, `RFC3339 timestamp`|
|`LessThanEqual `, `Lte`|`<=`|`string`, `float64`, `RFC3339 timestamp`|

## Documentation

Expand Down
44 changes: 40 additions & 4 deletions exp.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
v = l.Value().Value
}
switch r.Value().Type {
case parse.T_IDENTIFIER:
Expand All @@ -100,6 +102,8 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
v = r.Value().Value
}
if v == "" {
return Equal(k, f), nil
Expand All @@ -123,6 +127,8 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
v = l.Value().Value
}
switch r.Value().Type {
case parse.T_IDENTIFIER:
Expand All @@ -135,14 +141,16 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
v = r.Value().Value
}
if v == "" {
return NotEqual(k, f), nil
}
return Not(Match(k, v)), nil
case parse.T_IS_GREATER:
var (
k string
k, tm string
v float64
l = t.Left()
r = t.Right()
Expand All @@ -156,6 +164,8 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
tm = l.Value().Value
}
switch r.Value().Type {
case parse.T_IDENTIFIER:
Expand All @@ -166,11 +176,16 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
tm = r.Value().Value
}
if tm != "" {
return TimeGreaterThan(k, tm), nil
}
return GreaterThan(k, v), nil
case parse.T_IS_GREATER_OR_EQUAL:
var (
k string
k, tm string
v float64
l = t.Left()
r = t.Right()
Expand All @@ -184,6 +199,8 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
tm = l.Value().Value
}
switch r.Value().Type {
case parse.T_IDENTIFIER:
Expand All @@ -194,11 +211,16 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
tm = r.Value().Value
}
if tm != ""{
return TimeGreaterOrEqual(k, tm), nil
}
return GreaterOrEqual(k, v), nil
case parse.T_IS_SMALLER:
var (
k string
k, tm string
v float64
l = t.Left()
r = t.Right()
Expand All @@ -212,6 +234,8 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
tm = l.Value().Value
}
switch r.Value().Type {
case parse.T_IDENTIFIER:
Expand All @@ -222,11 +246,16 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
tm = r.Value().Value
}
if tm != "" {
return TimeLessThan(k, tm), nil
}
return LessThan(k, v), nil
case parse.T_IS_SMALLER_OR_EQUAL:
var (
k string
k , tm string
v float64
l = t.Left()
r = t.Right()
Expand All @@ -240,6 +269,8 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
tm = l.Value().Value
}
switch r.Value().Type {
case parse.T_IDENTIFIER:
Expand All @@ -250,6 +281,11 @@ func visit(t parse.Tree) (Exp, error) {
if err != nil {
return nil, err
}
case parse.T_TIMESTAMP:
tm = r.Value().Value
}
if tm != ""{
return TimeLessOrEqual(k, tm), nil
}
return LessOrEqual(k, v), nil
}
Expand Down
22 changes: 22 additions & 0 deletions exp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,25 @@ func TestParse(t *testing.T) {
t.Logf("%s", exp)
}
}

func TestTimestampParse(t *testing.T) {
m := Map{
"timestamp": "2020-04-07T20:05:00+05:30",
}
for _, s := range []string{
`(timestamp == "2020-04-07T20:05:00+05:30")`,
`(timestamp > "2020-04-07T20:04:00+05:30")`,
`(timestamp < "2020-04-07T20:06:00+05:30")`,
`(timestamp <= "2020-04-07T20:05:00+05:30")`,
`(timestamp >= "2020-04-07T20:05:00+05:30")`,
} {
exp, err := Parse(s)
if err != nil {
t.Fatal(err)
}
if !exp.Eval(m) {
t.Error("unexpected output")
}
t.Logf("%s", exp)
}
}
16 changes: 15 additions & 1 deletion parse/lex.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"bytes"
"fmt"
"strings"
"time"
"unicode"
"unicode/utf8"
)
Expand Down Expand Up @@ -36,6 +37,7 @@ const (
T_NUMBER
T_STRING
T_BOOLEAN
T_TIMESTAMP

T_LOGICAL_AND
T_LOGICAL_OR
Expand Down Expand Up @@ -331,7 +333,11 @@ loop:
switch l.next() {
case '"':
l.backup()
l.emit(T_STRING)
if isTimestamp(l.buffer()) {
l.emit(T_TIMESTAMP)
} else {
l.emit(T_STRING)
}
l.next()
l.ignore()
break loop
Expand Down Expand Up @@ -380,3 +386,11 @@ func isAlphanum(r rune) bool {
func isOperator(r rune) bool {
return r == '=' || r == '!' || r == '>' || r == '<' || r == '&' || r == '|'
}

// isTimestamp reports whether r is a Timestamp. Timestamp supports time.RFC3339
func isTimestamp(r string) bool {
if _, err := time.Parse(time.RFC3339, r); err != nil {
return false
}
return true
}
2 changes: 1 addition & 1 deletion parse/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ loop:
node.right = newTree()
stack.push(node)
node = node.right
case T_IDENTIFIER, T_NUMBER, T_STRING, T_BOOLEAN:
case T_IDENTIFIER, T_NUMBER, T_STRING, T_BOOLEAN, T_TIMESTAMP:
node.value = token
node, err = stack.pop()
if err != nil {
Expand Down
Loading