github.com/linchen2chris/hugo@v0.0.0-20230307053224-cec209389705/hugolib/dates_test.go (about)

     1  // Copyright 2021 The Hugo Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package hugolib
    15  
    16  import (
    17  	"fmt"
    18  
    19  	qt "github.com/frankban/quicktest"
    20  
    21  	"strings"
    22  	"testing"
    23  )
    24  
    25  func TestDateFormatMultilingual(t *testing.T) {
    26  	b := newTestSitesBuilder(t)
    27  	b.WithConfigFile("toml", `
    28  baseURL = "https://example.org"
    29  
    30  defaultContentLanguage = "en"
    31  defaultContentLanguageInSubDir = true
    32  
    33  [languages]
    34  [languages.en]
    35  weight=10
    36  [languages.nn]
    37  weight=20
    38  	
    39  `)
    40  
    41  	pageWithDate := `---
    42  title: Page
    43  date: 2021-07-18
    44  ---	
    45  `
    46  
    47  	b.WithContent(
    48  		"_index.en.md", pageWithDate,
    49  		"_index.nn.md", pageWithDate,
    50  	)
    51  
    52  	b.WithTemplatesAdded("index.html", `
    53  Date: {{ .Date | time.Format ":date_long" }}
    54  	`)
    55  
    56  	b.Build(BuildCfg{})
    57  
    58  	b.AssertFileContent("public/en/index.html", `Date: July 18, 2021`)
    59  	b.AssertFileContent("public/nn/index.html", `Date: 18. juli 2021`)
    60  
    61  }
    62  
    63  func TestTimeZones(t *testing.T) {
    64  	b := newTestSitesBuilder(t)
    65  	b.WithConfigFile("toml", `
    66  baseURL = "https://example.org"
    67  
    68  defaultContentLanguage = "en"
    69  defaultContentLanguageInSubDir = true
    70  
    71  [languages]
    72  [languages.en]
    73  timeZone="UTC"
    74  weight=10
    75  [languages.nn]
    76  timeZone="America/Antigua"
    77  weight=20
    78  	
    79  `)
    80  
    81  	const (
    82  		pageTemplYaml = `---
    83  title: Page
    84  date: %s
    85  lastMod: %s
    86  publishDate: %s
    87  expiryDate: %s
    88  ---	
    89  `
    90  
    91  		pageTemplTOML = `+++
    92  title="Page"
    93  date=%s
    94  lastMod=%s
    95  publishDate=%s
    96  expiryDate=%s
    97  +++
    98  `
    99  
   100  		shortDateTempl = `%d-07-%d`
   101  		longDateTempl  = `%d-07-%d 15:28:01`
   102  	)
   103  
   104  	createPageContent := func(pageTempl, dateTempl string, quoted bool) string {
   105  		createDate := func(year, i int) string {
   106  			d := fmt.Sprintf(dateTempl, year, i)
   107  			if quoted {
   108  				return fmt.Sprintf("%q", d)
   109  			}
   110  
   111  			return d
   112  		}
   113  
   114  		return fmt.Sprintf(
   115  			pageTempl,
   116  			createDate(2021, 10),
   117  			createDate(2021, 11),
   118  			createDate(2021, 12),
   119  			createDate(2099, 13), // This test will fail in 2099 :-)
   120  		)
   121  	}
   122  
   123  	b.WithContent(
   124  		// YAML
   125  		"short-date-yaml-unqouted.en.md", createPageContent(pageTemplYaml, shortDateTempl, false),
   126  		"short-date-yaml-unqouted.nn.md", createPageContent(pageTemplYaml, shortDateTempl, false),
   127  		"short-date-yaml-qouted.en.md", createPageContent(pageTemplYaml, shortDateTempl, true),
   128  		"short-date-yaml-qouted.nn.md", createPageContent(pageTemplYaml, shortDateTempl, true),
   129  		"long-date-yaml-unqouted.en.md", createPageContent(pageTemplYaml, longDateTempl, false),
   130  		"long-date-yaml-unqouted.nn.md", createPageContent(pageTemplYaml, longDateTempl, false),
   131  		// TOML
   132  		"short-date-toml-unqouted.en.md", createPageContent(pageTemplTOML, shortDateTempl, false),
   133  		"short-date-toml-unqouted.nn.md", createPageContent(pageTemplTOML, shortDateTempl, false),
   134  		"short-date-toml-qouted.en.md", createPageContent(pageTemplTOML, shortDateTempl, true),
   135  		"short-date-toml-qouted.nn.md", createPageContent(pageTemplTOML, shortDateTempl, true),
   136  	)
   137  
   138  	const datesTempl = `
   139  Date: {{ .Date | safeHTML  }}
   140  Lastmod: {{ .Lastmod | safeHTML  }}
   141  PublishDate: {{ .PublishDate | safeHTML  }}
   142  ExpiryDate: {{ .ExpiryDate | safeHTML  }}
   143  
   144  	`
   145  
   146  	b.WithTemplatesAdded(
   147  		"_default/single.html", datesTempl,
   148  	)
   149  
   150  	b.Build(BuildCfg{})
   151  
   152  	expectShortDateEn := `
   153  Date: 2021-07-10 00:00:00 +0000 UTC
   154  Lastmod: 2021-07-11 00:00:00 +0000 UTC
   155  PublishDate: 2021-07-12 00:00:00 +0000 UTC
   156  ExpiryDate: 2099-07-13 00:00:00 +0000 UTC`
   157  
   158  	expectShortDateNn := strings.ReplaceAll(expectShortDateEn, "+0000 UTC", "-0400 AST")
   159  
   160  	expectLongDateEn := `
   161  Date: 2021-07-10 15:28:01 +0000 UTC
   162  Lastmod: 2021-07-11 15:28:01 +0000 UTC
   163  PublishDate: 2021-07-12 15:28:01 +0000 UTC
   164  ExpiryDate: 2099-07-13 15:28:01 +0000 UTC`
   165  
   166  	expectLongDateNn := strings.ReplaceAll(expectLongDateEn, "+0000 UTC", "-0400 AST")
   167  
   168  	// TODO(bep) create a common proposal for go-yaml, go-toml
   169  	// for a custom date parser hook to handle these time zones.
   170  	// JSON is omitted from this test as JSON does no (to my knowledge)
   171  	// have date literals.
   172  
   173  	// YAML
   174  	// Note: This is with go-yaml v2, I suspect v3 will fail with the unquouted values.
   175  	b.AssertFileContent("public/en/short-date-yaml-unqouted/index.html", expectShortDateEn)
   176  	b.AssertFileContent("public/nn/short-date-yaml-unqouted/index.html", expectShortDateNn)
   177  	b.AssertFileContent("public/en/short-date-yaml-qouted/index.html", expectShortDateEn)
   178  	b.AssertFileContent("public/nn/short-date-yaml-qouted/index.html", expectShortDateNn)
   179  
   180  	b.AssertFileContent("public/en/long-date-yaml-unqouted/index.html", expectLongDateEn)
   181  	b.AssertFileContent("public/nn/long-date-yaml-unqouted/index.html", expectLongDateNn)
   182  
   183  	// TOML
   184  	// These fails: TOML (Burnt Sushi) defaults to local timezone.
   185  	// TODO(bep) check go-toml
   186  	b.AssertFileContent("public/en/short-date-toml-unqouted/index.html", expectShortDateEn)
   187  	b.AssertFileContent("public/nn/short-date-toml-unqouted/index.html", expectShortDateNn)
   188  	b.AssertFileContent("public/en/short-date-toml-qouted/index.html", expectShortDateEn)
   189  	b.AssertFileContent("public/nn/short-date-toml-qouted/index.html", expectShortDateNn)
   190  
   191  }
   192  
   193  // Issue 8832
   194  func TestTimeZoneInvalid(t *testing.T) {
   195  	b := newTestSitesBuilder(t)
   196  
   197  	b.WithConfigFile("toml", `
   198  	
   199  timeZone = "America/LosAngeles"   # Should be America/Los_Angeles
   200  `)
   201  
   202  	err := b.CreateSitesE()
   203  	b.Assert(err, qt.Not(qt.IsNil))
   204  	b.Assert(err.Error(), qt.Contains, `failed to load config: invalid timeZone for language "en": unknown time zone America/LosAngeles`)
   205  }
   206  
   207  // Issue 8835
   208  func TestTimeOnError(t *testing.T) {
   209  	b := newTestSitesBuilder(t)
   210  
   211  	b.WithTemplates("index.html", `time: {{ time "2020-10-20" "invalid-timezone" }}`)
   212  	b.WithContent("p1.md", "")
   213  
   214  	b.Assert(b.BuildE(BuildCfg{}), qt.Not(qt.IsNil))
   215  
   216  }
   217  
   218  func TestTOMLDates(t *testing.T) {
   219  	t.Parallel()
   220  
   221  	files := `
   222  -- config.toml --
   223  timeZone = "America/Los_Angeles"
   224  -- content/_index.md --
   225  ---
   226  date: "2020-10-20"
   227  ---
   228  -- content/p1.md --
   229  +++
   230  title = "TOML Date with UTC offset"
   231  date = 2021-08-16T06:00:00+00:00
   232  +++
   233  
   234  
   235  ## Foo
   236  -- data/mydata.toml --
   237  date = 2020-10-20
   238  talks = [
   239  	{ date = 2017-01-23, name = "Past talk 1" },
   240  	{ date = 2017-01-24, name = "Past talk 2" },
   241  	{ date = 2017-01-26, name = "Past talk 3" },
   242  	{ date = 2050-02-12, name = "Future talk 1" },
   243  	{ date = 2050-02-13, name = "Future talk 2" },
   244  ]
   245  -- layouts/index.html --
   246  {{ $futureTalks := where site.Data.mydata.talks "date" ">" now }}
   247  {{ $pastTalks := where site.Data.mydata.talks "date" "<" now }}
   248  
   249  {{ $homeDate := site.Home.Date }}
   250  {{ $p1Date := (site.GetPage "p1").Date }}
   251  Future talks: {{ len $futureTalks }}
   252  Past talks: {{ len $pastTalks }}
   253  
   254  Home's Date should be greater than past: {{ gt $homeDate (index $pastTalks 0).date }}
   255  Home's Date should be less than future: {{ lt $homeDate (index $futureTalks 0).date }}
   256  Home's Date should be equal mydata date: {{ eq $homeDate site.Data.mydata.date }}
   257  Full time: {{ $p1Date | time.Format ":time_full" }}
   258  `
   259  
   260  	b := NewIntegrationTestBuilder(
   261  		IntegrationTestConfig{
   262  			T:           t,
   263  			TxtarString: files,
   264  		},
   265  	).Build()
   266  
   267  	b.AssertFileContent("public/index.html", `
   268  Future talks: 2
   269  Past talks: 3
   270  Home's Date should be greater than past: true
   271  Home's Date should be less than future: true
   272  Home's Date should be equal mydata date: true
   273  Full time: 6:00:00 am UTC
   274  `)
   275  }