Skip to content

Commit 1b4c423

Browse files
jmooringbep
authored andcommitted
resources/page: Allow full datetime prefix in filenames
Allow YYYY-MM-DD-HH-MM-SS prefix when extracting date from file names. This is in addition to the YYYY-MM-DD prefix that is already supported. Closes #13830
1 parent 1e9a0b9 commit 1b4c423

File tree

2 files changed

+66
-30
lines changed

2 files changed

+66
-30
lines changed

resources/page/pagemeta/page_frontmatter.go

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -457,26 +457,43 @@ func (f FrontMatterHandler) IsDateKey(key string) bool {
457457
return f.allDateKeys[key]
458458
}
459459

460-
// A Zero date is a signal that the name can not be parsed.
461-
// This follows the format as outlined in Jekyll, https://jekyllrb.com/docs/posts/:
462-
// "Where YEAR is a four-digit number, MONTH and DAY are both two-digit numbers"
463-
func dateAndSlugFromBaseFilename(location *time.Location, name string) (time.Time, string) {
464-
withoutExt, _ := paths.FileAndExt(name)
465-
466-
if len(withoutExt) < 10 {
467-
// This can not be a date.
460+
// dateAndSlugFromBaseFilename returns a time.Time value (resolved to the
461+
// default system location) and a slug, extracted by parsing the provided path.
462+
// Parsing supports YYYY-MM-DD-HH-MM-SS and YYYY-MM-DD date/time formats.
463+
// Within the YYYY-MM-DD-HH-MM-SS format, the date and time values may be
464+
// separated by any character including a space (e.g., YYYY-MM-DD HH-MM-SS).
465+
func dateAndSlugFromBaseFilename(location *time.Location, path string) (time.Time, string) {
466+
base, _ := paths.FileAndExt(path)
467+
468+
if len(base) < 10 {
469+
// Not long enough to start with a YYYY-MM-DD date.
468470
return time.Time{}, ""
469471
}
470472

471-
d, err := htime.ToTimeInDefaultLocationE(withoutExt[:10], location)
472-
if err != nil {
473-
return time.Time{}, ""
473+
// Delimiters allowed between the date and the slug.
474+
delimiters := " -_"
475+
476+
if len(base) >= 19 {
477+
// Attempt to parse a YYYY-MM-DD-HH-MM-SS date-time prefix.
478+
ds := base[:10]
479+
ts := strings.ReplaceAll(base[11:19], "-", ":")
480+
481+
d, err := htime.ToTimeInDefaultLocationE(ds+"T"+ts, location)
482+
if err == nil {
483+
return d, strings.Trim(base[19:], delimiters)
484+
}
474485
}
475486

476-
// Be a little lenient with the format here.
477-
slug := strings.Trim(withoutExt[10:], " -_")
487+
// Attempt to parse a YYYY-MM-DD date prefix.
488+
ds := base[:10]
489+
490+
d, err := htime.ToTimeInDefaultLocationE(ds, location)
491+
if err == nil {
492+
return d, strings.Trim(base[10:], delimiters)
493+
}
478494

479-
return d, slug
495+
// If no date is defined, return the zero time instant.
496+
return time.Time{}, ""
480497
}
481498

482499
type frontMatterFieldHandler func(d *FrontMatterDescriptor) (bool, error)

resources/page/pagemeta/pagemeta_test.go

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -102,27 +102,46 @@ func TestDateAndSlugFromBaseFilename(t *testing.T) {
102102
date string
103103
slug string
104104
}{
105-
{"page.md", "0001-01-01", ""},
106-
{"2012-09-12-page.md", "2012-09-12", "page"},
107-
{"2018-02-28-page.md", "2018-02-28", "page"},
108-
{"2018-02-28_page.md", "2018-02-28", "page"},
109-
{"2018-02-28 page.md", "2018-02-28", "page"},
110-
{"2018-02-28page.md", "2018-02-28", "page"},
111-
{"2018-02-28-.md", "2018-02-28", ""},
112-
{"2018-02-28-.md", "2018-02-28", ""},
113-
{"2018-02-28.md", "2018-02-28", ""},
114-
{"2018-02-28-page", "2018-02-28", "page"},
115-
{"2012-9-12-page.md", "0001-01-01", ""},
116-
{"asdfasdf.md", "0001-01-01", ""},
105+
// date
106+
{"2025-07-04 page.md", "2025-07-04T00:00:00+02:00", "page"},
107+
{"2025-07-04-page.md", "2025-07-04T00:00:00+02:00", "page"},
108+
{"2025-07-04_page.md", "2025-07-04T00:00:00+02:00", "page"},
109+
{"2025-07-04page.md", "2025-07-04T00:00:00+02:00", "page"},
110+
{"2025-07-04", "2025-07-04T00:00:00+02:00", ""},
111+
{"2025-07-04-.md", "2025-07-04T00:00:00+02:00", ""},
112+
{"2025-07-04.md", "2025-07-04T00:00:00+02:00", ""},
113+
// date and time
114+
{"2025-07-04-22-17-13 page.md", "2025-07-04T22:17:13+02:00", "page"},
115+
{"2025-07-04-22-17-13-page.md", "2025-07-04T22:17:13+02:00", "page"},
116+
{"2025-07-04-22-17-13_page.md", "2025-07-04T22:17:13+02:00", "page"},
117+
{"2025-07-04-22-17-13page.md", "2025-07-04T22:17:13+02:00", "page"},
118+
{"2025-07-04-22-17-13", "2025-07-04T22:17:13+02:00", ""},
119+
{"2025-07-04-22-17-13-.md", "2025-07-04T22:17:13+02:00", ""},
120+
{"2025-07-04-22-17-13.md", "2025-07-04T22:17:13+02:00", ""},
121+
// date and time with other separators between the two
122+
{"2025-07-04T22-17-13.md", "2025-07-04T22:17:13+02:00", ""},
123+
{"2025-07-04 22-17-13.md", "2025-07-04T22:17:13+02:00", ""},
124+
// no date or time
125+
{"something.md", "0001-01-01T00:00:00+00:00", ""}, // 9 chars
126+
{"some-thing-.md", "0001-01-01T00:00:00+00:00", ""}, // 10 chars
127+
{"somethingsomething.md", "0001-01-01T00:00:00+00:00", ""}, // 18 chars
128+
{"something-something.md", "0001-01-01T00:00:00+00:00", ""}, // 19 chars
129+
{"something-something-else.md", "0001-01-01T00:00:00+00:00", ""}, // 27 chars
130+
// invalid
131+
{"2025-07-4-page.md", "0001-01-01T00:00:00+00:00", ""},
132+
{"2025-07-4-22-17-13-page.md", "0001-01-01T00:00:00+00:00", ""},
133+
{"asdfasdf.md", "0001-01-01T00:00:00+00:00", ""},
117134
}
118135

136+
location, err := time.LoadLocation("Europe/Oslo")
137+
if err != nil {
138+
t.Error("Unable to determine location from given time zone")
139+
}
119140
for _, test := range tests {
120-
expecteFDate, err := time.Parse("2006-01-02", test.date)
121-
c.Assert(err, qt.IsNil)
122141

123-
gotDate, gotSlug := dateAndSlugFromBaseFilename(time.UTC, test.name)
142+
gotDate, gotSlug := dateAndSlugFromBaseFilename(location, test.name)
124143

125-
c.Assert(gotDate, qt.Equals, expecteFDate)
144+
c.Assert(gotDate.Format("2006-01-02T15:04:05-07:00"), qt.Equals, test.date)
126145
c.Assert(gotSlug, qt.Equals, test.slug)
127146

128147
}

0 commit comments

Comments
 (0)