diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2022-06-06 09:48:40 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2022-06-07 13:02:58 +0200 |
commit | 0566bbf7c7f2898fcd1d6156b27733cd48aa0449 (patch) | |
tree | 69ee0bde4d334cb0565afd5fb4e17247c946aad9 /common | |
parent | 534e7155bb504682a37f5663d8c913e439b11e07 (diff) |
Fix raw TOML dates in where/eq
Note that this has only been a problem with "raw dates" in TOML files in /data and similar. The predefined front matter
dates `.Date` etc. are converted to a Go Time and has worked fine even after upgrading to v2 of the go-toml lib.
Fixes #9979
Diffstat (limited to 'common')
-rw-r--r-- | common/hreflect/helpers.go | 40 | ||||
-rw-r--r-- | common/htime/time.go | 12 |
2 files changed, 47 insertions, 5 deletions
diff --git a/common/hreflect/helpers.go b/common/hreflect/helpers.go index e1c01456d..1b7e5acf7 100644 --- a/common/hreflect/helpers.go +++ b/common/hreflect/helpers.go @@ -20,7 +20,9 @@ import ( "context" "reflect" "sync" + "time" + "github.com/gohugoio/hugo/common/htime" "github.com/gohugoio/hugo/common/types" ) @@ -168,6 +170,44 @@ func GetMethodIndexByName(tp reflect.Type, name string) int { return m.Index } +var ( + timeType = reflect.TypeOf((*time.Time)(nil)).Elem() + asTimeProviderType = reflect.TypeOf((*htime.AsTimeProvider)(nil)).Elem() +) + +// IsTime returns whether tp is a time.Time type or if it can be converted into one +// in ToTime. +func IsTime(tp reflect.Type) bool { + if tp == timeType { + return true + } + + if tp.Implements(asTimeProviderType) { + return true + } + return false +} + +// AsTime returns v as a time.Time if possible. +// The given location is only used if the value implements AsTimeProvider (e.g. go-toml local). +// A zero Time and false is returned if this isn't possible. +// Note that this function does not accept string dates. +func AsTime(v reflect.Value, loc *time.Location) (time.Time, bool) { + if v.Kind() == reflect.Interface { + return AsTime(v.Elem(), loc) + } + + if v.Type() == timeType { + return v.Interface().(time.Time), true + } + + if v.Type().Implements(asTimeProviderType) { + return v.Interface().(htime.AsTimeProvider).AsTime(loc), true + } + + return time.Time{}, false +} + // Based on: https://github.com/golang/go/blob/178a2c42254166cffed1b25fb1d3c7a5727cada6/src/text/template/exec.go#L931 func indirectInterface(v reflect.Value) reflect.Value { if v.Kind() != reflect.Interface { diff --git a/common/htime/time.go b/common/htime/time.go index 052a45ed1..d30ecf7e1 100644 --- a/common/htime/time.go +++ b/common/htime/time.go @@ -20,8 +20,6 @@ import ( "github.com/bep/clock" "github.com/spf13/cast" - toml "github.com/pelletier/go-toml/v2" - "github.com/gohugoio/locales" ) @@ -139,13 +137,12 @@ func (f TimeFormatter) Format(t time.Time, layout string) string { func ToTimeInDefaultLocationE(i any, location *time.Location) (tim time.Time, err error) { switch vv := i.(type) { - case toml.LocalDate: - return vv.AsTime(location), nil - case toml.LocalDateTime: + case AsTimeProvider: return vv.AsTime(location), nil // issue #8895 // datetimes parsed by `go-toml` have empty zone name // convert back them into string and use `cast` + // TODO(bep) add tests, make sure we really need this. case time.Time: i = vv.Format(time.RFC3339) } @@ -161,3 +158,8 @@ func Now() time.Time { func Since(t time.Time) time.Duration { return Clock.Since(t) } + +// AsTimeProvider is implemented by go-toml's LocalDate and LocalDateTime. +type AsTimeProvider interface { + AsTime(zone *time.Location) time.Time +} |