Skip to content

Commit

Permalink
[WIP] Use UTC Hour, Day, Month, Year for comparison
Browse files Browse the repository at this point in the history
The time.Hour() function, for example, returns the value
of hour stored, without accounting for timezone information.
E.g. for timestamp, 2019-05-28T14:41:57+30:00, the Hour value
would be 14 whereas when we use this value for comparison,
that would not correctly compare two timestamps.

Now, we use UTC value of hour for creating index and for
comparison to ensure that we correctly compare all timestamps
having timezone information.
  • Loading branch information
mangalaman93 committed Apr 11, 2019
1 parent a614ee3 commit 25ecece
Show file tree
Hide file tree
Showing 3 changed files with 288 additions and 36 deletions.
27 changes: 18 additions & 9 deletions query/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ make : string @index(term) .
year : int .
previous_model : uid @reverse .
created_at : datetime @index(hour) .
updated_at : datetime @index(year) .
`

func populateCluster() {
Expand Down Expand Up @@ -344,9 +345,9 @@ func populateCluster() {
<31> <friend> <24> .
<23> <friend> <1> .
<2> <best_friend> <64> .
<3> <best_friend> <64> .
<4> <best_friend> <64> .
<2> <best_friend> <64> (since=2019-03-28T14:41:57+30:00) .
<3> <best_friend> <64> (since=2018-03-24T14:41:57+05:30) .
<4> <best_friend> <64> (since=2019-03-27) .
<1> <age> "38" .
<23> <age> "15" .
Expand Down Expand Up @@ -574,12 +575,20 @@ func populateCluster() {

// Add data for datetime tests
addTriplesToCluster(`
<301> <created_at> "2019-03-28T14:41:57+30:00" .
<302> <created_at> "2019-03-28T13:41:57+29:00" .
<303> <created_at> "2019-03-27T14:41:57+06:00" .
<304> <created_at> "2019-03-28T15:41:57+30:00" .
<305> <created_at> "2019-03-28T13:41:57+30:00" .
<306> <created_at> "2019-03-24T14:41:57+05:30" .
<301> <created_at> "2019-03-28T14:41:57+30:00" (modified_at=2019-05-28T14:41:57+30:00) .
<302> <created_at> "2019-03-28T13:41:57+29:00" (modified_at=2019-03-28T14:41:57+30:00) .
<303> <created_at> "2019-03-27T14:41:57+06:00" (modified_at=2019-03-29) .
<304> <created_at> "2019-03-28T15:41:57+30:00" (modified_at=2019-03-27T14:41:57+06:00) .
<305> <created_at> "2019-03-28T13:41:57+30:00" (modified_at=2019-03-28) .
<306> <created_at> "2019-03-24T14:41:57+05:30" (modified_at=2019-03-28T13:41:57+30:00) .
<307> <created_at> "2019-05-28T14:41:57+30:00" .
<301> <updated_at> "2019-03-28T14:41:57+30:00" (modified_at=2019-05-28) .
<302> <updated_at> "2019-03-28T13:41:57+29:00" (modified_at=2019-03-28T14:41:57+30:00) .
<303> <updated_at> "2019-03-27T14:41:57+06:00" (modified_at=2019-03-28T13:41:57+29:00) .
<304> <updated_at> "2019-03-28T15:41:57+30:00" .
<305> <updated_at> "2019-03-28T13:41:57+30:00" (modified_at=2019-03-28T15:41:57+30:00) .
<306> <updated_at> "2019-03-24T14:41:57+05:30" (modified_at=2019-03-28T13:41:57+30:00) .
<307> <updated_at> "2019-05-28T14:41:57+30:00" (modified_at=2019-03-24T14:41:57+05:30) .
`)
}
277 changes: 260 additions & 17 deletions query/query0_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package query

import (
"fmt"
"os"
"testing"

Expand Down Expand Up @@ -1824,34 +1825,276 @@ func TestNonFlattenedResponse(t *testing.T) {

}

func TestDateTimeQuery1(t *testing.T) {
query := `
{
q(func: ge(created_at, "2019-03-28T13:41:57")) {
func TestDateTimeQuery(t *testing.T) {
var query string

// Test 20
query = `
{
q(func: has(best_friend)){
uid
best_friend @facets(orderasc: since) {
uid
created_at
}
}
`
js := processQueryNoErr(t, query)
}
}
`
fmt.Println(processQueryNoErr(t, query))
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x133","created_at":"2019-05-28T14:41:57+30:00"}]}}`,
js)
`{"data":{"q":[{"uid":"0x2","best_friend":{"uid":"0x40","best_friend|since":"2019-03-28T14:41:57+30:00"}},{"uid":"0x4","best_friend":{"uid":"0x40","best_friend|since":"2019-03-27T00:00:00Z"}},{"uid":"0x3","best_friend":{"uid":"0x40","best_friend|since":"2018-03-24T14:41:57+05:30"}}]}}`,
processQueryNoErr(t, query))

// Test 19
query = `
{
q(func: has(created_at), orderdesc: created_at) {
uid
created_at
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x133","created_at":"2019-05-28T14:41:57+30:00"},{"uid":"0x130","created_at":"2019-03-28T15:41:57+30:00"},{"uid":"0x12d","created_at":"2019-03-28T14:41:57+30:00"},{"uid":"0x12e","created_at":"2019-03-28T13:41:57+29:00"},{"uid":"0x12f","created_at":"2019-03-27T14:41:57+06:00"},{"uid":"0x131","created_at":"2019-03-28T13:41:57+30:00"},{"uid":"0x132","created_at":"2019-03-24T14:41:57+05:30"}]}}`,
processQueryNoErr(t, query))

func TestDateTimeQuery2(t *testing.T) {
query := `
// Test 18
query = `
{
q(func: has(best_friend)) @cascade {
uid
best_friend @facets(lt(since, "2019-03-24")) @facets(since) {
uid
}
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x3","best_friend":{"uid":"0x40","best_friend|since":"2018-03-24T14:41:57+05:30"}}]}}`,
processQueryNoErr(t, query))

// Test 17
query = `
{
q(func: has(best_friend)) @cascade {
uid
best_friend @facets(gt(since, "2019-03-27")) @facets(since) {
uid
}
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x2","best_friend":{"uid":"0x40","best_friend|since":"2019-03-28T14:41:57+30:00"}}]}}`,
processQueryNoErr(t, query))

// Test 16
query = `
{
q(func: gt(created_at, "2019-03-28")) {
uid
created_at @facets(modified_at)
updated_at @facets(modified_at)
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x133","created_at":"2019-05-28T14:41:57+30:00","updated_at|modified_at":"2019-03-24T14:41:57+05:30","updated_at":"2019-05-28T14:41:57+30:00"}]}}`,
processQueryNoErr(t, query))

// Test 15
query = `
{
q(func: gt(age, 15)) @filter(gt(graduation, "1932") AND lt(graduation, "1934")) {
uid
graduation
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x1f","graduation":["1935-01-01T00:00:00Z","1933-01-01T00:00:00Z"]}]}}`,
processQueryNoErr(t, query))

// Test 14
query = `
{
q(func: gt(age, 15)) @filter(le(graduation, "1932") OR gt(graduation, "1936")) {
uid
graduation
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x1","graduation":["1932-01-01T00:00:00Z"]}]}}`,
processQueryNoErr(t, query))

// Test 13
query = `
{
q(func: ge(created_at, "2019-03-28T13:41:57+00:00")) {
q(func: gt(age, 15)) @filter(lt(graduation, "1932") AND gt(graduation, "1936")) {
uid
created_at
graduation
}
}
}
`
js := processQueryNoErr(t, query)
require.JSONEq(t,
`{"data":{"q":[]}}`,
processQueryNoErr(t, query))

// Test 12
query = `
{
q(func: le(dob, "1909-05-05")) {
uid
dob
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x18","dob":"1909-05-05T00:00:00Z"},{"uid":"0x19","dob":"1909-01-10T00:00:00Z"},{"uid":"0x1f","dob":"1901-01-15T00:00:00Z"}]}}`,
processQueryNoErr(t, query))

// Test 11
query = `
{
q(func: le(dob, "1909-05-05T00:00:00+05:30")) {
uid
dob
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x19","dob":"1909-01-10T00:00:00Z"},{"uid":"0x1f","dob":"1901-01-15T00:00:00Z"}]}}`,
processQueryNoErr(t, query))

// Test 10
query = `
{
q(func: eq(graduation, "1932-01-01T00:00:00+05:30")) {
uid
graduation
}
}
`
require.JSONEq(t,
`{"data":{"q":[]}}`,
processQueryNoErr(t, query))

// Test 9
query = `
{
q(func: eq(graduation, "1932")) {
uid
graduation
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x1","graduation":["1932-01-01T00:00:00Z"]}]}}`,
processQueryNoErr(t, query))

// Test 8
query = `
{
q(func: lt(graduation, "1933")) {
uid
graduation
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x1","graduation":["1932-01-01T00:00:00Z"]}]}}`,
processQueryNoErr(t, query))

// Test 7
query = `
{
q(func: gt(graduation, "1932")) {
uid
graduation
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x1f","graduation":["1935-01-01T00:00:00Z","1933-01-01T00:00:00Z"]}]}}`,
processQueryNoErr(t, query))

// Test 6
query = `
{
q(func: le(updated_at, "2019-03-27T14:41:56+06:00")) {
uid
updated_at
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x131","updated_at":"2019-03-28T13:41:57+30:00"},{"uid":"0x132","updated_at":"2019-03-24T14:41:57+05:30"}]}}`,
processQueryNoErr(t, query))

// Test 5
query = `
{
q(func: ge(updated_at, "2019-03-28T13:41:57+00:00")) {
uid
updated_at
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x133","updated_at":"2019-05-28T14:41:57+30:00"}]}}`,
processQueryNoErr(t, query))

// Test 4
query = `
{
q(func: ge(updated_at, "2019-03-28T13:41:57")) {
uid
updated_at
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x133","updated_at":"2019-05-28T14:41:57+30:00"}]}}`,
processQueryNoErr(t, query))

// Test 3
query = `
{
q(func: le(created_at, "2019-03-27T14:41:56+06:00")) {
uid
created_at
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x131","created_at":"2019-03-28T13:41:57+30:00"},{"uid":"0x132","created_at":"2019-03-24T14:41:57+05:30"}]}}`,
processQueryNoErr(t, query))

// Test 2
query = `
{
q(func: ge(created_at, "2019-03-28T13:41:57+00:00")) {
uid
created_at
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x133","created_at":"2019-05-28T14:41:57+30:00"}]}}`,
js)
processQueryNoErr(t, query))

// Test 1
query = `
{
q(func: ge(created_at, "2019-03-28T13:41:57")) {
uid
created_at
}
}
`
require.JSONEq(t,
`{"data":{"q":[{"uid":"0x133","created_at":"2019-05-28T14:41:57+30:00"}]}}`,
processQueryNoErr(t, query))
}

var client *dgo.Dgraph
Expand Down
20 changes: 10 additions & 10 deletions tok/tok.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ func (t YearTokenizer) Type() string { return "datetime" }
func (t YearTokenizer) Tokens(v interface{}) ([]string, error) {
tval := v.(time.Time)
buf := make([]byte, 2)
binary.BigEndian.PutUint16(buf[0:2], uint16(tval.Year()))
binary.BigEndian.PutUint16(buf[0:2], uint16(tval.UTC().Year()))
return []string{string(buf)}, nil
}
func (t YearTokenizer) Identifier() byte { return IdentYear }
Expand All @@ -222,8 +222,8 @@ func (t MonthTokenizer) Type() string { return "datetime" }
func (t MonthTokenizer) Tokens(v interface{}) ([]string, error) {
tval := v.(time.Time)
buf := make([]byte, 4)
binary.BigEndian.PutUint16(buf[0:2], uint16(tval.Year()))
binary.BigEndian.PutUint16(buf[2:4], uint16(tval.Month()))
binary.BigEndian.PutUint16(buf[0:2], uint16(tval.UTC().Year()))
binary.BigEndian.PutUint16(buf[2:4], uint16(tval.UTC().Month()))
return []string{string(buf)}, nil
}
func (t MonthTokenizer) Identifier() byte { return IdentMonth }
Expand All @@ -237,9 +237,9 @@ func (t DayTokenizer) Type() string { return "datetime" }
func (t DayTokenizer) Tokens(v interface{}) ([]string, error) {
tval := v.(time.Time)
buf := make([]byte, 6)
binary.BigEndian.PutUint16(buf[0:2], uint16(tval.Year()))
binary.BigEndian.PutUint16(buf[2:4], uint16(tval.Month()))
binary.BigEndian.PutUint16(buf[4:6], uint16(tval.Day()))
binary.BigEndian.PutUint16(buf[0:2], uint16(tval.UTC().Year()))
binary.BigEndian.PutUint16(buf[2:4], uint16(tval.UTC().Month()))
binary.BigEndian.PutUint16(buf[4:6], uint16(tval.UTC().Day()))
return []string{string(buf)}, nil
}
func (t DayTokenizer) Identifier() byte { return IdentDay }
Expand All @@ -253,10 +253,10 @@ func (t HourTokenizer) Type() string { return "datetime" }
func (t HourTokenizer) Tokens(v interface{}) ([]string, error) {
tval := v.(time.Time)
buf := make([]byte, 8)
binary.BigEndian.PutUint16(buf[0:2], uint16(tval.Year()))
binary.BigEndian.PutUint16(buf[2:4], uint16(tval.Month()))
binary.BigEndian.PutUint16(buf[4:6], uint16(tval.Day()))
binary.BigEndian.PutUint16(buf[6:8], uint16(tval.Hour()))
binary.BigEndian.PutUint16(buf[0:2], uint16(tval.UTC().Year()))
binary.BigEndian.PutUint16(buf[2:4], uint16(tval.UTC().Month()))
binary.BigEndian.PutUint16(buf[4:6], uint16(tval.UTC().Day()))
binary.BigEndian.PutUint16(buf[6:8], uint16(tval.UTC().Hour()))
return []string{string(buf)}, nil
}
func (t HourTokenizer) Identifier() byte { return IdentHour }
Expand Down

0 comments on commit 25ecece

Please sign in to comment.