diff --git a/go.mod b/go.mod index 6ccc10bbc..692056834 100644 --- a/go.mod +++ b/go.mod @@ -58,6 +58,7 @@ require ( github.com/stretchr/testify v1.7.0 github.com/swaggo/swag v1.7.8 github.com/ulule/limiter/v3 v3.9.0 + github.com/vectordotdev/go-datemath v0.1.1-0.20211214182920-0a4ac8742b93 // indirect github.com/yuin/goldmark v1.4.4 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 golang.org/x/image v0.0.0-20211028202545-6944b10bf410 diff --git a/go.sum b/go.sum index 76b7fbdd1..b30c2a9a6 100644 --- a/go.sum +++ b/go.sum @@ -785,6 +785,8 @@ github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52 github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vectordotdev/go-datemath v0.1.1-0.20211214182920-0a4ac8742b93 h1:bT0ZMfsMi2Xh8dopgxhFT+OJH88QITHpdppdkG1rXJQ= +github.com/vectordotdev/go-datemath v0.1.1-0.20211214182920-0a4ac8742b93/go.mod h1:PnwzbSst7KD3vpBzzlntZU5gjVa455Uqa5QPiKSYJzQ= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= diff --git a/pkg/integrations/task_collection_test.go b/pkg/integrations/task_collection_test.go index bbd64c255..e1e11e811 100644 --- a/pkg/integrations/task_collection_test.go +++ b/pkg/integrations/task_collection_test.go @@ -17,12 +17,11 @@ package integrations import ( - "net/url" - "testing" - "code.vikunja.io/api/pkg/models" "code.vikunja.io/web/handler" "github.com/stretchr/testify/assert" + "net/url" + "testing" ) func TestTaskCollection(t *testing.T) { @@ -244,12 +243,37 @@ func TestTaskCollection(t *testing.T) { // the current date. assert.Equal(t, "[]\n", rec.Body.String()) }) + t.Run("unix timestamps", func(t *testing.T) { + rec, err := testHandler.testReadAllWithUser( + url.Values{ + "filter_by": []string{"start_date", "end_date", "due_date"}, + "filter_value": []string{"1544500000", "1513164001", "1543500000"}, + "filter_comparator": []string{"greater", "less", "greater"}, + }, + urlParams, + ) + assert.NoError(t, err) + assert.NotContains(t, rec.Body.String(), `task #1`) + assert.NotContains(t, rec.Body.String(), `task #2`) + assert.NotContains(t, rec.Body.String(), `task #3`) + assert.NotContains(t, rec.Body.String(), `task #4`) + assert.Contains(t, rec.Body.String(), `task #5`) + assert.Contains(t, rec.Body.String(), `task #6`) + assert.Contains(t, rec.Body.String(), `task #7`) + assert.NotContains(t, rec.Body.String(), `task #8`) + assert.Contains(t, rec.Body.String(), `task #9`) + assert.NotContains(t, rec.Body.String(), `task #10`) + assert.NotContains(t, rec.Body.String(), `task #11`) + assert.NotContains(t, rec.Body.String(), `task #12`) + assert.NotContains(t, rec.Body.String(), `task #13`) + assert.NotContains(t, rec.Body.String(), `task #14`) + }) }) t.Run("invalid date", func(t *testing.T) { _, err := testHandler.testReadAllWithUser( url.Values{ "filter_by": []string{"due_date"}, - "filter_value": []string{"1540000000"}, + "filter_value": []string{"invalid"}, "filter_comparator": []string{"greater"}, }, nil, @@ -451,7 +475,7 @@ func TestTaskCollection(t *testing.T) { _, err := testHandler.testReadAllWithUser( url.Values{ "filter_by": []string{"due_date"}, - "filter_value": []string{"1540000000"}, + "filter_value": []string{"invalid"}, "filter_comparator": []string{"greater"}, }, nil, diff --git a/pkg/models/task_collection_filter.go b/pkg/models/task_collection_filter.go index 4b8ed1421..0e86a683b 100644 --- a/pkg/models/task_collection_filter.go +++ b/pkg/models/task_collection_filter.go @@ -25,6 +25,7 @@ import ( "code.vikunja.io/api/pkg/config" "github.com/iancoleman/strcase" + "github.com/vectordotdev/go-datemath" "xorm.io/xorm/schemas" ) @@ -159,8 +160,14 @@ func getValueForField(field reflect.StructField, rawValue string) (value interfa value, err = strconv.ParseBool(rawValue) case reflect.Struct: if field.Type == schemas.TimeType { - value, err = time.Parse(time.RFC3339, rawValue) - value = value.(time.Time).In(config.GetTimeZone()) + var t datemath.Expression + t, err = datemath.Parse(rawValue) + if err == nil { + value = t.Time(datemath.WithLocation(config.GetTimeZone())) + } else { + value, err = time.Parse(time.RFC3339, rawValue) + value = value.(time.Time).In(config.GetTimeZone()) + } } case reflect.Slice: // If this is a slice of pointers we're dealing with some property which is a relation