From efa5760db5ef39ae084bfccb5b8f756c7b117a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 27 Jul 2021 13:45:05 +0200 Subject: Add timezone support for front matter dates without one Fixes #8810 --- tpl/time/init.go | 2 +- tpl/time/time.go | 69 +++++++++------------------------------------------ tpl/time/time_test.go | 16 ++++++++---- 3 files changed, 24 insertions(+), 63 deletions(-) (limited to 'tpl') diff --git a/tpl/time/init.go b/tpl/time/init.go index 775878f71..6cbdccb8f 100644 --- a/tpl/time/init.go +++ b/tpl/time/init.go @@ -26,7 +26,7 @@ func init() { if d.Language == nil { panic("Language must be set") } - ctx := New(langs.GetTranslator(d.Language)) + ctx := New(langs.GetTranslator(d.Language), langs.GetLocation(d.Language)) ns := &internal.TemplateFuncsNamespace{ Name: name, diff --git a/tpl/time/time.go b/tpl/time/time.go index 6fb901cc3..a59d85b06 100644 --- a/tpl/time/time.go +++ b/tpl/time/time.go @@ -16,6 +16,7 @@ package time import ( "fmt" + "time" _time "time" "github.com/gohugoio/hugo/common/htime" @@ -25,83 +26,37 @@ import ( "github.com/spf13/cast" ) -var timeFormats = []string{ - _time.RFC3339, - "2006-01-02T15:04:05", // iso8601 without timezone - _time.RFC1123Z, - _time.RFC1123, - _time.RFC822Z, - _time.RFC822, - _time.RFC850, - _time.ANSIC, - _time.UnixDate, - _time.RubyDate, - "2006-01-02 15:04:05.999999999 -0700 MST", // Time.String() - "2006-01-02", - "02 Jan 2006", - "2006-01-02T15:04:05-0700", // RFC3339 without timezone hh:mm colon - "2006-01-02 15:04:05 -07:00", - "2006-01-02 15:04:05 -0700", - "2006-01-02 15:04:05Z07:00", // RFC3339 without T - "2006-01-02 15:04:05Z0700", // RFC3339 without T or timezone hh:mm colon - "2006-01-02 15:04:05", - _time.Kitchen, - _time.Stamp, - _time.StampMilli, - _time.StampMicro, - _time.StampNano, -} - // New returns a new instance of the time-namespaced template functions. -func New(translator locales.Translator) *Namespace { +func New(translator locales.Translator, location *time.Location) *Namespace { return &Namespace{ timeFormatter: htime.NewTimeFormatter(translator), + location: location, } } // Namespace provides template functions for the "time" namespace. type Namespace struct { timeFormatter htime.TimeFormatter + location *time.Location } // AsTime converts the textual representation of the datetime string into // a time.Time interface. func (ns *Namespace) AsTime(v interface{}, args ...interface{}) (interface{}, error) { - if len(args) == 0 { - t, err := cast.ToTimeE(v) + loc := ns.location + if len(args) > 0 { + locStr, err := cast.ToStringE(args[0]) if err != nil { return nil, err } - - return t, nil - } - - timeStr, err := cast.ToStringE(v) - if err != nil { - return nil, err - } - - locStr, err := cast.ToStringE(args[0]) - if err != nil { - return nil, err - } - - loc, err := _time.LoadLocation(locStr) - if err != nil { - return nil, err - } - - // Note: Cast currently doesn't support time with non-default locations. For now, just inlining this. - // Reference: https://github.com/spf13/cast/pull/80 - - for _, dateType := range timeFormats { - t, err2 := _time.ParseInLocation(dateType, timeStr, loc) - if err2 == nil { - return t, nil + loc, err = _time.LoadLocation(locStr) + if err != nil { + return nil, err } } - return nil, fmt.Errorf("Unable to ParseInLocation using date %q with timezone %q", v, loc) + return cast.ToTimeInDefaultLocationE(v, loc) + } // Format converts the textual representation of the datetime string into diff --git a/tpl/time/time_test.go b/tpl/time/time_test.go index ed689f9a8..71899cc65 100644 --- a/tpl/time/time_test.go +++ b/tpl/time/time_test.go @@ -23,14 +23,16 @@ import ( func TestTimeLocation(t *testing.T) { t.Parallel() - ns := New(translators.Get("en")) + loc, _ := time.LoadLocation("America/Antigua") + ns := New(translators.Get("en"), loc) for i, test := range []struct { value string - location string + location interface{} expect interface{} }{ {"2020-10-20", "", "2020-10-20 00:00:00 +0000 UTC"}, + {"2020-10-20", nil, "2020-10-20 00:00:00 -0400 AST"}, {"2020-10-20", "America/New_York", "2020-10-20 00:00:00 -0400 EDT"}, {"2020-01-20", "America/New_York", "2020-01-20 00:00:00 -0500 EST"}, {"2020-10-20 20:33:59", "", "2020-10-20 20:33:59 +0000 UTC"}, @@ -41,7 +43,11 @@ func TestTimeLocation(t *testing.T) { {"2020-01-20", "invalid-timezone", false}, // unknown time zone invalid-timezone {"invalid-value", "", false}, } { - result, err := ns.AsTime(test.value, test.location) + var args []interface{} + if test.location != nil { + args = append(args, test.location) + } + result, err := ns.AsTime(test.value, args...) if b, ok := test.expect.(bool); ok && !b { if err == nil { t.Errorf("[%d] AsTime didn't return an expected error, got %v", i, result) @@ -61,7 +67,7 @@ func TestTimeLocation(t *testing.T) { func TestFormat(t *testing.T) { t.Parallel() - ns := New(translators.Get("en")) + ns := New(translators.Get("en"), time.UTC) for i, test := range []struct { layout string @@ -101,7 +107,7 @@ func TestFormat(t *testing.T) { func TestDuration(t *testing.T) { t.Parallel() - ns := New(translators.Get("en")) + ns := New(translators.Get("en"), time.UTC) for i, test := range []struct { unit interface{} -- cgit v1.2.3