Fail on invalid time zone
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 1 Aug 2021 09:50:12 +0000 (11:50 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 1 Aug 2021 11:39:30 +0000 (13:39 +0200)
Fixes #8832

hugolib/dates_test.go
langs/config.go
langs/language.go

index c9a33e0f8b0c9887311643fbf78f9799be0c9f32..dfcb681a3a8e75111377b373b503799eb3cc12a6 100644 (file)
@@ -15,6 +15,9 @@ package hugolib
 
 import (
        "fmt"
+
+       qt "github.com/frankban/quicktest"
+
        "strings"
        "testing"
 )
@@ -186,3 +189,17 @@ ExpiryDate: 2099-07-13 15:28:01 +0000 UTC`
        b.AssertFileContent("public/nn/short-date-toml-qouted/index.html", expectShortDateNn)
 
 }
+
+// Issue 8832
+func TestTimeZoneInvalid(t *testing.T) {
+       b := newTestSitesBuilder(t)
+
+       b.WithConfigFile("toml", `
+       
+timeZone = "America/LosAngeles"   # Should be America/Los_Angeles
+`)
+
+       err := b.CreateSitesE()
+       b.Assert(err, qt.Not(qt.IsNil))
+       b.Assert(err.Error(), qt.Contains, `failed to load config: invalid timeZone for language "en": unknown time zone America/LosAngeles`)
+}
index fe4ed9d14d756a182b10265f4899d3eb1466a95f..f79b7dd0ac233c7fd39e2e6e54368f3346dde727 100644 (file)
@@ -161,6 +161,12 @@ func LoadLanguageSettings(cfg config.Provider, oldLangs Languages) (c LanguagesC
                }
        }
 
+       for _, language := range c.Languages {
+               if language.initErr != nil {
+                       return c, language.initErr
+               }
+       }
+
        return c, nil
 }
 
@@ -197,6 +203,10 @@ func toSortedLanguages(cfg config.Provider, l map[string]interface{}) (Languages
                                for k, vv := range m {
                                        language.SetParam(k, vv)
                                }
+                       case "timezone":
+                               if err := language.loadLocation(cast.ToString(v)); err != nil {
+                                       return nil, err
+                               }
                        }
 
                        // Put all into the Params map
index 758729c2523357ffd6447aa56c56345c58535fe3..46f1be60e5af009df09d489513e6e0068bf666f1 100644 (file)
@@ -19,6 +19,8 @@ import (
        "sync"
        "time"
 
+       "github.com/pkg/errors"
+
        translators "github.com/bep/gotranslators"
        "github.com/go-playground/locales"
        "github.com/gohugoio/hugo/common/maps"
@@ -77,8 +79,10 @@ type Language struct {
        // TODO(bep) do the same for some of the others.
        translator locales.Translator
 
-       locationInit sync.Once
-       location     *time.Location
+       location *time.Location
+
+       // Error during initialization. Will fail the buld.
+       initErr error
 }
 
 func (l *Language) String() string {
@@ -113,6 +117,11 @@ func NewLanguage(lang string, cfg config.Provider) *Language {
                params:     params,
                translator: translator,
        }
+
+       if err := l.loadLocation(cfg.GetString("timeZone")); err != nil {
+               l.initErr = err
+       }
+
        return l
 }
 
@@ -248,18 +257,6 @@ func (l *Language) IsSet(key string) bool {
        return l.Cfg.IsSet(key)
 }
 
-func (l *Language) getLocation() *time.Location {
-       l.locationInit.Do(func() {
-               location, err := time.LoadLocation(l.GetString("timeZone"))
-               if err != nil {
-                       location = time.UTC
-               }
-               l.location = location
-       })
-
-       return l.location
-}
-
 // Internal access to unexported Language fields.
 // This construct is to prevent them from leaking to the templates.
 
@@ -268,5 +265,15 @@ func GetTranslator(l *Language) locales.Translator {
 }
 
 func GetLocation(l *Language) *time.Location {
-       return l.getLocation()
+       return l.location
+}
+
+func (l *Language) loadLocation(tzStr string) error {
+       location, err := time.LoadLocation(tzStr)
+       if err != nil {
+               return errors.Wrapf(err, "invalid timeZone for language %q", l.Lang)
+       }
+       l.location = location
+
+       return nil
 }