Parsing dates in templates

I’m trying to build an online CV with Hugo, the idea being that each entry can have frontmatter like:

+++
title = "Company name"
startdate = "2012-07"
enddate = "2014-09-13"
+++

which can then be parsed by the the template to produce something like:

Company name
July 2012 to September 2014

However, I’m struggling to find a way to do this. I understand that Go templates do not allow you to access arbitrary functions (e.g. time.Parse) and that you must pass in the functions you need as a funcMap. I can’t find any way to do this inside Hugo - ideally it’d be possible to say

{{ parse .Params.startdate "January 2006"}}

but I have no idea how I can make the parse function available without actually modifying Hugo itself.

Any ideas?

I take this from memory, but I’m pretty sure time.Parse isn’t available as a template function – neither from Go’s builtins nor Hugo. It could be added, of course, but I’m struggling with understanding the use case.

mydate.Format makes sense, but that is available.

date = "2015-01-17"

and then

{{ .Date.Format "January 2006" }}

works fine, because the date field gets automatically cast to a Time.

However,

startdate = "2015-01-17"

and

{{ .Params.startdate.Format "January 2006" }}

does not work, because startdate remains a String rather than being cast to Time.

I have now discovered that you can do the following:

startdate = 2013-07-24T00:00:00Z

and

{{ .Params.startdate.Format "January 2006" }}

because TOML has native support for ISO8601 dates and they are parsed to a Time rather than a String. However, this isn’t ideal, because TOML only supports ‘full Zulu’ dates - you can’t write

startdate = 2013-07-24

In fact, this actually crashes Hugo with the following error:

ERROR: 2015/01/18 Error parsing page meta data for entry.md
ERROR: 2015/01/18 Near line 4, key 'startdate': Near line 5: Expected 'T' in ISO8601 datetime, but found '\n' instead.
ERROR: 2015/01/18 Near line 4, key 'startdate': Near line 5: Expected 'T' in ISO8601 datetime, but found '\n' instead.
CRITICAL: 2015/01/18 Errors rendering pages: Near line 4, key 'startdate': Near line 5: Expected 'T' in ISO8601 datetime, but found '\n' instead.

I can live with writing the ‘full Zulu’ dates for now, but I’d like to find a neater solution. Maybe the answer is that the TOML spec needs changing!

2 Likes

For reference:

Coincidentally, similar discussions happened in Issue #235: format string as date on GitHub back on March 20, 2014.

@spf13 concluded that it was a good idea to implement a new dateFormat function for this purpose, and welcome a pull request.

Fixed in

2 Likes

I’m quite new to hugo and am getting the following error:

$ hugo version
Hugo Static Site Generator v0.14-DEV BuildDate: 2015-02-22T08:09:28Z

$ hugo server --theme=lanyon --buildDrafts
ERROR: 2015/02/25 template: theme/post/li.html:1:25: executing "theme/post/li.html" at <.Site.Params.DateFor...>: invalid value; expected string in theme/post/li.html

ERROR: 2015/02/25 Error while rendering page post/post/first.md: template: theme/post/single.html:5:47: executing “theme/post/single.html” at <.Site.Params.DateFor…>: invalid value; expected string

And something pretty similar with the beg theme too. I’ve tried all sorts but I’m not getting very far. Here is what I have:

+++
title = "About Hugo"
date        = "2013-06-21T11:27:27-04:00"
menu = "main"
+++

And I’ve tried:

date = "2013-06-21T11:27:27-04:00"
date = 2013-06-21T11:27:27-04:00
date = 2013-06-21
date = "2013-06-21"

With the beg theme I get:

$ hugo server --theme=beg --buildDrafts
ERROR: 2015/02/25 template: theme/_default/li.html:6:39: executing "theme/_default/li.html" at <.Site.Params.DateFor...>: invalid value; expected string in theme/_default/li.html

Any ideas? Thanks.

You need a line in your config.toml to define the DateForm parameter:

[Params]
	DateForm = "Jan 2 2006"
2 Likes

Yes that fixed it thanks. So does the toml precide over the yml? I already had:

Params:
  DateForm: "Mon, Jan 2, 2006"

I used the TOML as an example, since that’s what I work with. If you had that in your config.yaml, it should have picked it up.

Did you have the default config.toml in your directory, alongside the YAML? I don’t know the rules that Hugo uses to pick config files if both are present.

I’m new to Hugo and don’t really understand the DateForm parameter (in the config file).

In the theme, I have: {{ .Date.Format .Site.Params.DateForm }}.
In the config file: DateForm = "02 Jan 2006".

That displays the date as “Sunday, Jul 19, 2015”. Oddly enough, when I remove the DateForm parameter from the theme, it works correctly:

In theme: {{ .Date.Format "02 Jan 2006" }} generates “19 Jul 2015” on the website.

How can I use the DateForm parameter so it outputs “19 Jul 2015”?

Edit: DateForm seems to be working now after I’ve restarted the Hugo webserver a few times now. It seems that changes in the config file aren’t picked up while Hugo is running.

Yes, the config file is only read on startup.

is dateFormat working for multilingual?
I used the simple way: substr and index of data:

{{ substr .Params.tarih 8 2 }} {{ index $.Site.Data.aylar (substr .Params.tarih 5 2 ) }} {{ substr .Params.tarih 0 4 }}

My dates are in format YYYY-MM-DD
And I get “12 Ağustos 2008” in Turkish.

Currently no.

I was hoping to use time.Parse to automatically set the expiryDate in an events archetype. Something like…

archetypes/events.md:

+++
{{- $eventDate := (getenv "EVENT_DATE") }}
eventDate = "{{ $eventDate }}"
expiryDate = "{{ (time.Parse time.RFC3339 $eventDate).AddDate 0 0 1 }}"
+++

Then I could just:

$ EVENT_DATE="2017-10-26T:17:00-07:00" hugo new events/myevent.md

…and not have to worry about copy/paste errors.

I’m pretty sure something like this will work:

expiryDate = "{{ (time $eventDate).Add (10 | duration "hour" ) }}"
1 Like

Thanks for the quick reply! I had tried (time $eventDate) and got a parse error, but looking back through my command history I found a typo in my date string. Doh!

Fixing that, using duration "hour", and formatting it back to the expected format works:

expiryDate = "{{ ((time $eventDate).Add (10 | duration "hour" )).Format "2006-01-02T15:04:05-07:00" }}"
3 Likes

Dear all
I know this post is rather old and it has been fixed. Nevertheless I stumbled on a situation where dateFormat does not seem to work.
CONTEXT: I have created a custom taxonomy “time” whose terms take the year and month of the publication date (e.g.: 2021-10).
AIM: I wish to use the year and month in the term to rebuild the date (with an arbitrary day say 02), so the term page shows the terms not as 2021-10 but as 2021 October.

WHAT I DID:
STEP1: Extract year and month from term (which is in the .Page.Title of a {{ range .Data.Terms.Alphabetical.Reverse }})
PageTitle: {{.Page.Title}} → returns 2021-10
{{$year := substr .Page.Title 0 4}} → returns 2021
{{$month := substr .Page.Title 5 2}} → returns 10
STEP2: Construct a string YYYY-MM-DD, taking $year for YYYY, $month for MM, and 02 for DD
{{$xxx := chomp (print $year “-” $month “-02”)}} → returns 2021-10-02
STEP3: Convert the string to a date
{{ dateFormat “2006-01” $xxx }}
The latter fails with the following message: “error calling dateFormat: unable to parse date: 2021–02”

HOWEVER THE FOLLOWING WORKS:
{{$example := “2021-10-02”}}
Original: {{$example}}
Type: {{ printf “%T” $example }}
Result formatted with dateFormat: {{ dateFormat “2006-01” $example}}
Result formatted with time.Format: {{ time.Format “2006-01” $example}}

I have tried playing with print and printf, maybe the value of $xxx should have quotes?
All help greatly appreciated.

Eureka!
In the frontmatter (yaml) time value needs to be in quotes:
time: ‘2021-10’
and then the code works!