Parsing custom date format (French, Spanish, ...)

Hi,
After looking at the docs and discussions I didn’t find an answer to the question:
Is it possible in a Hugo template or Shortcode file to parse custom date formats ?

Context:

Imagine a CV page theme created via Hugo (“CV.md”), this CV page is made of shortcodes for example one like this:

{{< cvSingleElement company="Google" title="Software R&D Engineer" location="Paris area, France" startdate="15/03/2021" enddate="10/09/2021" >}}
Job description here.....
{{</ cvSingleElement >}}

As you can see there is two shortcode variables startdate and enddate, these dates aren’t using the US format but the French one (see this page : https://docs.oracle.com/cd/E19455-01/806-0169/overview-7/index.html)

In the shortcode file I want to parse these date and do some operation to display this:
Mar 2021 - Sep 2021 (6 mos)

The Issue:

Currently it seems I cannot convert / parse these dates strings into time object since they aren’t “US style” formatted.

There is Go functions that do this job like with time.ParseInLocation() (see here), but currently not available in Hugo.

A not working idea:

I tried to create a workaround by creating a parseDate shortcode in hugo using a config string named dateFormat:

params:
  dateFormat: "DD/MM/YYYY"

Then in the shortcode parseDate.html:

{{ $format := `` }}
{{ if isset .Site.Params "dateformat" }}
{{ $format = .Site.Params.dateFormat }}
{{ else if .Get "dateformat" }}
{{ $format = .Get "dateformat" }}
{{ else }}
{{ errorf "dateformat is required, set it on your params config file or pass itas named parameter." "" }}
{{ end }}

{{ $format = replaceRE "DD" "(?P<day>\\d{2})" $format }}
{{ $format = replaceRE "MM" "(?P<month>\\d{2})" $format }}
{{ $format = replaceRE "YYYY" "(?P<year>\\d{4})" $format }}
{{ $format = delimit (slice "^" $format "$") "" }}
{{ $format }}

{{ $date := .Get 0 }}
{{ $findResult := findRE `^(?P<day>\d{2})/(?P<month>\d{2})/(?P<year>\d{4})$` $date }}

But I got two big issues:

1. As you can see in the last line I didn’t used $format since somehow the variable was a string:
"^(?P<day>\d{2})-(?P<month>\d{2})-(?P<year>\d{4})$"
and not a regex string like:
`^(?P<day>\d{2})-(?P<month>\d{2})-(?P<year>\d{4})$`
Notice backticks instead of " "
2. And the most important issue, findRE ignore groups since internal the method used is FindAllString and not FindStringSubmatch (check this for live demo)

Question

Is it possible or planned to be able to parse international date in Hugo ?
it’s frustrating since if you have a valid time you can format it like you wish, but it’s not possible to parse it.

Thanks for your time,
Long life to Hugo and thanks for the devs and the people of this forum!

First, you cannot parse either of these formats with the time.AsTime method:

{{ time.AsTime "07/12/2022" }} --> error calling AsTime: unable to parse date
{{ time.AsTime "12/07/2022" }} --> error calling AsTime: unable to parse date

Second, although this is not what you asked for, the simplest approach is to use the (less ambiguous) ISO 8601 format:

{{ time.AsTime "2022-07-12" }}

Finally, if you want to use the dd/mm/yyyy format in your shortcode parameters, you could do something like:

layouts/shortcodes/cvSingleElement.html

{{ $startDate := partial "cast-to-time.html" (.Get "startdate") }}
{{ $endDate := partial "cast-to-time.html" (.Get "enddate") }}

layouts/partials/cast-to-time.html

{{ $dateParts := split . "/" }}
{{ if lt (len $dateParts) 3 }}
  {{ errorf "Cannot cast %s to time.Time value" . }}
{{ end }}
{{ return (time.AsTime (printf "%s-%s-%s" (index $dateParts 2) (index $dateParts 1) (index $dateParts 0))) }}

Thanks for the workaround.
But I would be better to have a true way to parse time like in Go we can use time.ParseInLocation() as you can see here : Go Playground - The Go Programming Language
(and the timeZone config variable already exists in Hugo)

Imagine this shortcode if for a Hugo theme shared will people from different countries, one use the 2006-01-02 format, another one use the 02/01/2006, another one use 02.01.2006 (like in Finland).

So without a proper “fix”, like adding a Hugo method time.Parse like the Parse method in Go, the workaround to handle all these common cases will be more like a big “hack” than a solution.

For now I will use the workaround you shared but still interested to get the point of view of the others members and devs.

Although I feel your pain, I guess there’s no point insisting on using national formats for internal purposes (I’m not talking about representation here!). If you need to convert those dates to whatever, you’re better off with ISO format.

I’m wondering about a US person living in Finnland… or maybe a German one living in the US. Are they going to use the US, the Finnish or the German format? That’s the charme of the ISO dates: You do not have to think about all these border cases since the format is always the same.

1 Like

I don’t understand your point, the objective is to facilitate the access to Hugo to the users and you want them to understand by themselves that due to a missing function they are forced to use a date formatted to the ISO standard.
For example, does your cousin or your nephew know the ISO standard of date formatting?

In the GO language there is time.ParseInLocation() and in Hugo users can set in there config file the timeZone variable.

So why not adding the ability to Parse date properly in Hugo?
Why forcing everyone using the ISO format to be able to cast this into a time ?

All the cases can be resolve by just adding a time.Parse method in Hugo that simply call the GO time.ParseInLocation() to return a time.time object.

For Hugo to be used by more people you have to stop thinking in terms of dev and think a bit in terms of user.

Sorry to be hard on you people but the answer “use the ISO format” isn’t a solution at all.

@bep , do you have an opinion on the matter ?

PS: This isn’t for internal usage, end users can use shortcodes in there Markdown pages and file startdate parameter to build there CV page.

My opinion on the matter is that you have too simplistic world view on this matter. You may find this issue worth reading:

That said,

  • You can set timeZone per language in your site config.
  • That timeZone will be used for most date parsing in Hugo (I say most, because there are some that is currently out of control, e.g. JSON/YAML date types).
  • That value will also be used in the time.Format template func which I recommend you use for all date formatting.

@bep Yes I know timeZone is used in HUGO but there is no possibility to parse with a “custom” format.

So ability to parse date with a timeFormat that isn’t in the hardcoded list like for French, Thai, Finnish, Spanish isn’t relevant ?

When you have a website and you need to enter a date in a calendar you enter MM-DD-YYYY or DD/MM/YYYY so why in hugo user passing date to a shortcode is forced to use YYYY-MM-DD ?

Last point, since in the hardcoded timeFormat array there is “02 Jan 2006”, why not having 02/01/2006 and 02.01.2006.

Or having a Hugo method:

{{ time.ParseWithFormat FORMAT INPUT [TIMEZONE] }}

{{ time.ParseWithFormat "02/01/2006" "15/03/2021" }} → "2021-03-15T00:00:00Z"

So user can specified in config Params the date format they used in there HUGO site and the theme can do:

{{ $startdate := .Get "startdate" }}
{{ if isset .Site.Params "dateformat" }}
{{ $startdate = time.ParseWithFormat .Site.Params.dateformat $startdate }} 
{{ else }}
{{ $startdate = time.AsTime $startdate }}
{{ end }}

And of course if user didn’t specified the dateformat and the input cannot be cast an error will be raise.

For the people who would come across this post, I opened a Feature issue on the Github project: