Add time.Time type support to where tpl func

`where` tpl function doesn't support `time.Time` type so if people want
to compare such values, it's required that these values are converted
into `int` and compare them.

This improves it. If `time.Time` values are passed to `where`, it
converts them into `int` internally, compares them and returns the
result.

See also
http://discuss.gohugo.io/t/future-posts-and-past-posts/1229/3
This commit is contained in:
Tatsushi Demachi 2015-05-26 19:33:32 +09:00 committed by bep
parent beaa09a7f6
commit 601a2ce124
2 changed files with 108 additions and 3 deletions

View file

@ -17,9 +17,6 @@ import (
"bytes"
"errors"
"fmt"
"github.com/spf13/cast"
"github.com/spf13/hugo/helpers"
jww "github.com/spf13/jwalterweatherman"
"html"
"html/template"
"os"
@ -27,6 +24,11 @@ import (
"sort"
"strconv"
"strings"
"time"
"github.com/spf13/cast"
"github.com/spf13/hugo/helpers"
jww "github.com/spf13/jwalterweatherman"
)
var funcMap template.FuncMap
@ -364,8 +366,16 @@ func First(limit interface{}, seq interface{}) (interface{}, error) {
var (
zero reflect.Value
errorType = reflect.TypeOf((*error)(nil)).Elem()
timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
)
func timeUnix(v reflect.Value) int64 {
if v.Type() != timeType {
panic("coding error: argument must be time.Time type reflect Value")
}
return v.MethodByName("Unix").Call([]reflect.Value{})[0].Int()
}
func evaluateSubElem(obj reflect.Value, elemName string) (reflect.Value, error) {
if !obj.IsValid() {
return zero, errors.New("can't evaluate an invalid value")
@ -459,6 +469,14 @@ func checkCondition(v, mv reflect.Value, op string) (bool, error) {
svp = &sv
smv := mv.String()
smvp = &smv
case reflect.Struct:
switch v.Type() {
case timeType:
iv := timeUnix(v)
ivp = &iv
imv := timeUnix(mv)
imvp = &imv
}
}
} else {
if mv.Kind() != reflect.Array && mv.Kind() != reflect.Slice {
@ -480,6 +498,15 @@ func checkCondition(v, mv reflect.Value, op string) (bool, error) {
for i := 0; i < mv.Len(); i++ {
sma = append(sma, mv.Index(i).String())
}
case reflect.Struct:
switch v.Type() {
case timeType:
iv := timeUnix(v)
ivp = &iv
for i := 0; i < mv.Len(); i++ {
ima = append(ima, timeUnix(mv.Index(i)))
}
}
}
}

View file

@ -479,6 +479,28 @@ type TstX struct {
unexported string
}
func TestTimeUnix(t *testing.T) {
var sec int64 = 1234567890
tv := reflect.ValueOf(time.Unix(sec, 0))
i := 1
res := timeUnix(tv)
if sec != res {
t.Errorf("[%d] timeUnix got %v but expected %v", i, res, sec)
}
i++
func(t *testing.T) {
defer func() {
if err := recover(); err == nil {
t.Errorf("[%d] timeUnix didn't return an expected error", i)
}
}()
iv := reflect.ValueOf(sec)
timeUnix(iv)
}(t)
}
func TestEvaluateSubElem(t *testing.T) {
tstx := TstX{A: "foo", B: "bar"}
var inner struct {
@ -543,20 +565,76 @@ func TestCheckCondition(t *testing.T) {
}{
{reflect.ValueOf(123), reflect.ValueOf(123), "", expect{true, false}},
{reflect.ValueOf("foo"), reflect.ValueOf("foo"), "", expect{true, false}},
{
reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
"",
expect{true, false},
},
{reflect.ValueOf(123), reflect.ValueOf(456), "!=", expect{true, false}},
{reflect.ValueOf("foo"), reflect.ValueOf("bar"), "!=", expect{true, false}},
{
reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)),
"!=",
expect{true, false},
},
{reflect.ValueOf(456), reflect.ValueOf(123), ">=", expect{true, false}},
{reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">=", expect{true, false}},
{
reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)),
">=",
expect{true, false},
},
{reflect.ValueOf(456), reflect.ValueOf(123), ">", expect{true, false}},
{reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">", expect{true, false}},
{
reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)),
">",
expect{true, false},
},
{reflect.ValueOf(123), reflect.ValueOf(456), "<=", expect{true, false}},
{reflect.ValueOf("bar"), reflect.ValueOf("foo"), "<=", expect{true, false}},
{
reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)),
reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
"<=",
expect{true, false},
},
{reflect.ValueOf(123), reflect.ValueOf(456), "<", expect{true, false}},
{reflect.ValueOf("bar"), reflect.ValueOf("foo"), "<", expect{true, false}},
{
reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)),
reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
"<",
expect{true, false},
},
{reflect.ValueOf(123), reflect.ValueOf([]int{123, 45, 678}), "in", expect{true, false}},
{reflect.ValueOf("foo"), reflect.ValueOf([]string{"foo", "bar", "baz"}), "in", expect{true, false}},
{
reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
reflect.ValueOf([]time.Time{
time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC),
time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC),
time.Date(2015, time.June, 26, 19, 18, 56, 12345, time.UTC),
}),
"in",
expect{true, false},
},
{reflect.ValueOf(123), reflect.ValueOf([]int{45, 678}), "not in", expect{true, false}},
{reflect.ValueOf("foo"), reflect.ValueOf([]string{"bar", "baz"}), "not in", expect{true, false}},
{
reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
reflect.ValueOf([]time.Time{
time.Date(2015, time.February, 26, 19, 18, 56, 12345, time.UTC),
time.Date(2015, time.March, 26, 19, 18, 56, 12345, time.UTC),
time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC),
}),
"not in",
expect{true, false},
},
{reflect.ValueOf("foo"), reflect.ValueOf("bar-foo-baz"), "in", expect{true, false}},
{reflect.ValueOf("foo"), reflect.ValueOf("bar--baz"), "not in", expect{true, false}},
{reflect.Value{}, reflect.ValueOf("foo"), "", expect{false, false}},