Repository: gohugoio/hugo (language: go)

Issue:
Validate the four predefined front matter date fields when type is string
with hugo v0.110.0+extended darwin/arm64 BuildDate=unknown from brew

With the following front matter on a page in index.md
<pre>
---
title: "foo"
date: 2023-02-010T17:46:51-06:00
draft: true
---
</pre>

Note the extra zero in the day portion of the date.

~~The page will not be generated and~~ no error message will be issued.  I would expect an error message about an unparsable date.




Discussion / hints:
I agree that it would be helpful if the 4 front matter date fields were validated for JSON and YAML. With these formats, any date that you provide is a string---there is not a native date type.

When using TOML, where dates are a native type, [github.com/pelletier/go-toml ](https://github.com/pelletier/go-toml) throws an error when an unquoted value _looks_ like a date but isn't a date.

The native date type provided by TOML is very useful when performing date comparisons involving custom date parameters in front matter.


Hi @snicolai @jmooring , 

I cannot reproduce on my end.

It does generate a page. 

On my side, if the date format is wrong, no matter how it's wrong, the date is displayed as "Monday, Jan 1, 0001"


![Screenshot from 2023-02-18 09-47-16](https://user-images.githubusercontent.com/25248744/219872117-4b2806a7-d9d4-4b61-9746-6af913483b6e.png)

Perhaps it does generate the page, but sorts it into the wrong location, with 100s of posts and a pagination on the main page, it's likely not to be found.
As I showed in my previous comment, the page gets generated but the date becomes "Monday, Jan 1, 0001".
If the sorting is based on the date, it is highly probable that it's the first item or the last item.
If not, can you at least provide steps to reproduce it?
It's also possible that the date is interpreted as being in the future, and in that case, no page is generated.

Fix patch:
diff --git a/hugolib/page__meta.go b/hugolib/page__meta.go
index 56e26ecdbc9..97a716b4370 100644
--- a/hugolib/page__meta.go
+++ b/hugolib/page__meta.go
@@ -425,6 +425,7 @@ func (p *pageState) setMetaPostParams() error {
 		ModTime:       mtime,
 		GitAuthorDate: gitAuthorDate,
 		Location:      langs.GetLocation(pm.s.Language()),
+		PathOrTitle:   p.pathOrTitle(),
 	}
 
 	// Handle the date separately
diff --git a/resources/page/pagemeta/page_frontmatter.go b/resources/page/pagemeta/page_frontmatter.go
index 0e0650934b3..9491bf1bcab 100644
--- a/resources/page/pagemeta/page_frontmatter.go
+++ b/resources/page/pagemeta/page_frontmatter.go
@@ -330,6 +330,9 @@ type FrontMatterDescriptor struct {
 	// if page is a leaf bundle, the bundle folder name (ContentBaseName).
 	BaseFilename string
 
+	// The Page's path if the page is backed by a file, else its title.
+	PathOrTitle string
+
 	// The content file's mod time.
 	ModTime time.Time
 
@@ -736,7 +739,7 @@ func (f *frontmatterFieldHandlers) newDateFieldHandler(key string, setter func(d
 			var err error
 			date, err = htime.ToTimeInDefaultLocationE(v, d.Location)
 			if err != nil {
-				return false, nil
+				return false, fmt.Errorf("invalid front matter: %s: %s: see %s", key, v, d.PathOrTitle)
 			}
 			d.PageConfig.Params[key] = date
 		}


Test patch:
diff --git a/hugolib/content_map_test.go b/hugolib/content_map_test.go
index 80a336f0af0..bf992007171 100644
--- a/hugolib/content_map_test.go
+++ b/hugolib/content_map_test.go
@@ -28,8 +28,8 @@ func TestContentMapSite(t *testing.T) {
 	pageTempl := `
 ---
 title: "Page %d"
-date: "2019-06-0%d"
-lastMod: "2019-06-0%d"
+date: "2019-06-%02d"
+lastMod: "2019-06-%02d"
 categories: [%q]
 ---
 
@@ -55,7 +55,6 @@ draft: true
 title: "Hugo Home"
 cascade:
     description: "Common Description"
-
 ---
 
 Home Content.
@@ -64,24 +63,24 @@ Home Content.
 	b.WithContent("blog/page1.md", createPage(1))
 	b.WithContent("blog/page2.md", createPage(2))
 	b.WithContent("blog/page3.md", createPage(3))
-	b.WithContent("blog/bundle/index.md", createPage(12))
+	b.WithContent("blog/bundle/index.md", createPage(4))
 	b.WithContent("blog/bundle/data.json", "data")
-	b.WithContent("blog/bundle/page.md", createPage(99))
-	b.WithContent("blog/subsection/_index.md", createPage(3))
+	b.WithContent("blog/bundle/page.md", createPage(5))
+	b.WithContent("blog/subsection/_index.md", createPage(6))
 	b.WithContent("blog/subsection/subdata.json", "data")
-	b.WithContent("blog/subsection/page4.md", createPage(8))
-	b.WithContent("blog/subsection/page5.md", createPage(10))
+	b.WithContent("blog/subsection/page4.md", createPage(7))
+	b.WithContent("blog/subsection/page5.md", createPage(8))
 	b.WithContent("blog/subsection/draft/index.md", draftTemplate)
 	b.WithContent("blog/subsection/draft/data.json", "data")
 	b.WithContent("blog/draftsection/_index.md", draftTemplate)
-	b.WithContent("blog/draftsection/page/index.md", createPage(12))
+	b.WithContent("blog/draftsection/page/index.md", createPage(9))
 	b.WithContent("blog/draftsection/page/folder/data.json", "data")
-	b.WithContent("blog/draftsection/sub/_index.md", createPage(12))
-	b.WithContent("blog/draftsection/sub/page.md", createPage(13))
-	b.WithContent("docs/page6.md", createPage(11))
-	b.WithContent("tags/_index.md", createPageInCategory(32, "sad"))
-	b.WithContent("overlap/_index.md", createPageInCategory(33, "sad"))
-	b.WithContent("overlap2/_index.md", createPage(34))
+	b.WithContent("blog/draftsection/sub/_index.md", createPage(10))
+	b.WithContent("blog/draftsection/sub/page.md", createPage(11))
+	b.WithContent("docs/page6.md", createPage(12))
+	b.WithContent("tags/_index.md", createPageInCategory(13, "sad"))
+	b.WithContent("overlap/_index.md", createPageInCategory(14, "sad"))
+	b.WithContent("overlap2/_index.md", createPage(15))
 
 	b.WithTemplatesAdded("layouts/index.html", `
 Num Regular: {{ len .Site.RegularPages }}|{{ range .Site.RegularPages }}{{ .RelPermalink }}|{{ end }}$
@@ -118,7 +117,7 @@ Pages: {{ range $blog.Pages }}{{ .RelPermalink }}|{{ end }}
 Sections: {{ range $home.Sections }}{{ .RelPermalink }}|{{ end }}:END
 Categories: {{ range .Site.Taxonomies.categories }}{{ .Page.RelPermalink }}; {{ .Page.Title }}; {{ .Count }}|{{ end }}:END
 Category Terms:  {{ $categories.Kind}}: {{ range $categories.Data.Terms.Alphabetical }}{{ .Page.RelPermalink }}; {{ .Page.Title }}; {{ .Count }}|{{ end }}:END
-Category Funny:  {{ $funny.Kind}}; {{ $funny.Data.Term }}: {{ range $funny.Pages }}{{ .RelPermalink }};|{{ end }}:END
+Category Funny:  {{ $funny.Kind}}; {{ $funny.Data.Term }}: {{ range $funny.Pages }}{{ .RelPermalink }}|{{ end }}:END
 Pag Num Pages: {{ len .Paginator.Pages }}
 Pag Blog Num Pages: {{ len $blog.Paginator.Pages }}
 Blog Num RegularPages: {{ len $blog.RegularPages }}|{{ range $blog.RegularPages }}P: {{ .RelPermalink }}|{{ end }}
@@ -142,11 +141,11 @@ Draft5: {{ if (.Site.GetPage "blog/draftsection/sub/page") }}FOUND{{ end }}|
         Main Sections: [blog]
         Pag Num Pages: 9
 
-      Home: Hugo Home|/|2019-06-08|Current Section: /|Resources:
-        Blog Section: Blogs|/blog/|2019-06-08|Current Section: /blog|Resources:
-        Blog Sub Section: Page 3|/blog/subsection/|2019-06-03|Current Section: /blog/subsection|Resources: application: /blog/subsection/subdata.json|
+      Home: Hugo Home|/|2019-06-15|Current Section: /|Resources:
+        Blog Section: Blogs|/blog/|2019-06-11|Current Section: /blog|Resources:
+        Blog Sub Section: Page 6|/blog/subsection/|2019-06-06|Current Section: /blog/subsection|Resources: application: /blog/subsection/subdata.json|
         Page: Page 1|/blog/page1/|2019-06-01|Current Section: /blog|Resources:
-        Bundle: Page 12|/blog/bundle/|0001-01-01|Current Section: /blog|Resources: application: /blog/bundle/data.json|page: |
+        Bundle: Page 4|/blog/bundle/|2019-06-04|Current Section: /blog|Resources: application: /blog/bundle/data.json|page: |
         IsDescendant: true: true true: true true: true true: true true: true false: false false: false
         IsAncestor: true: true true: true true: true true: true true: true true: true false: false false: false false: false  false: false
         IsDescendant overlap1: false: false
@@ -157,11 +156,11 @@ Draft5: {{ if (.Site.GetPage "blog/draftsection/sub/page") }}FOUND{{ end }}|
         InSection: true: true false: false
         Next: /blog/page3/
         NextInSection: /blog/page3/
-        Pages: /blog/page3/|/blog/subsection/|/blog/page2/|/blog/page1/|/blog/bundle/|
-        Sections: /blog/|/docs/|/overlap/|/overlap2/|:END
+		Pages: /blog/subsection/|/blog/bundle/|/blog/page3/|/blog/page2/|/blog/page1/|
+		Sections: /overlap2/|/overlap/|/docs/|/blog/|:END
 		Categories: /categories/funny/; Funny; 12|/categories/sad/; Sad; 2|:END
         Category Terms:  taxonomy: /categories/funny/; Funny; 12|/categories/sad/; Sad; 2|:END
-		Category Funny:  term; funny: /blog/subsection/page4/;|/blog/page3/;|/blog/subsection/;|/blog/page2/;|/blog/page1/;|/blog/subsection/page5/;|/docs/page6/;|/blog/bundle/;|/blog/draftsection/page/;|/blog/draftsection/sub/;|/blog/draftsection/sub/page/;|/overlap2/;|:END
+		Category Funny:  term; funny: /overlap2/|/docs/page6/|/blog/draftsection/sub/page/|/blog/draftsection/sub/|/blog/draftsection/page/|/blog/subsection/page5/|/blog/subsection/page4/|/blog/subsection/|/blog/bundle/|/blog/page3/|/blog/page2/|/blog/page1/|:END
  		Pag Num Pages: 9
         Pag Blog Num Pages: 4
         Blog Num RegularPages: 4