Add time durations in frontmatter?

Hello, it’s me again.

A part of the website I’m working on is a discography catalog, and among other things, I have an array of time durations for the tracks in a release in the frontmatter, e.g., [10m30s, 6m9s, 12m0s, 8m7s, 8m31s, 14m41s]

i would like to display the sum of these durations on the release’s page. How would I do this? I can’t wrap my head around Hugo and Go’s time functions, and I’m not even sure whether this is possible without using something like JS. Also, am I using the right format for the duration strings?

Thank you so much in advance!

Without knowing about duration strings, you could range through each duration, parse it into min and sec, convert into seconds, add it as a number not string to a summation variable. Then when your done with the range, split the time back into equivalent minutes and seconds.

1 Like

Yes! Thanks to your suggestions I was able to do it. Thank you so much!

I’ll leave what I did here if anyone else wants to do this:

First, I formatted the frontmatter to look like this:

["00:10:30", "00:06:09", "00:12:00", "00:08:07", "00:08:31", "00:14:41"]

Then, I created a $total variable to hold the final tally in seconds.

Next, I wrote a range statement for this array, and inside it I created these variables to represent the hours, minutes, and seconds (the dot refers to the array):

{{ $times := split . ":" }}
{{ $hours := 0 }}
{{ $minutes := 0 }}
{{ $seconds := 0 }}

I then made a few if else statements to check if these values, with the leading 0s removed, are null; it outputs 0 if they are and the number without the leading 0s if they are not:

{{ if (eq (strings.TrimLeft "0" (index $times 0) ) "") }}
{{ $hours = int "0" }}
{{ else }}
{{ $hours = int (strings.TrimLeft "0" (index $times 0)) }}
{{ end }}
{{ if (eq (strings.TrimLeft "0" (index $times 1) ) "") }}
{{ $minutes = int "0" }}
{{ else }}
{{ $minutes = int (strings.TrimLeft "0" (index $times 1)) }}
{{ end }}
{{ if (eq (strings.TrimLeft "0" (index $times 2) ) "") }
{{ $seconds = int "0" }}
{{ else }}
{{ $seconds = int (strings.TrimLeft "0" (index $times 2)) }}
{{ end }}

Then, I converted the hours and minutes to seconds…

{{ $convHours := mul $hours 3600 }}
{{ $convMinutes := mul $minutes 60 }}

…added these and the seconds value together…

{{ $totalSeconds := add (add $convMinutes $convHours) $seconds }}`

…and then added this to the $total:

{{ $total = add $total $totalSeconds }}

Here, I ended the range, and I converted the $total back to individual time units, making sure to cast them as ints:

{{ $totalHours := int (math.Floor (div $total 3600)) }}
{{ $totalMinutes := int (math.Floor (div $total 60)) }}
{{ $totalSeconds := int (mod $total 60) }}

And lastly, I displayed them the way I want:

{{ printf "%02d" $totalHours }}:{{ printf "%02d" $totalMinutes }}:{{printf "%02d" $totalSeconds }}

So altogether my code looks like this:

{{ $total := 0 }}
{{ range $.Params.tracklengths }}
        {{ $times := split . ":" }}
		{{ $hours := 0 }}	
		{{ $minutes := 0 }}
		{{ $seconds := 0 }}
		{{ if (eq (strings.TrimLeft "0" (index $times 0) ) "") }}
			{{ $hours = int "0" }}
		{{ else }}
			{{ $hours = int (strings.TrimLeft "0" (index $times 0)) }}
		{{ end }}
		{{ if (eq (strings.TrimLeft "0" (index $times 1) ) "") }}
			{{ $minutes = int "0" }}
		{{ else }}
			{{ $minutes = int (strings.TrimLeft "0" (index $times 1)) }}
		{{ end }}
		{{ if (eq (strings.TrimLeft "0" (index $times 2) ) "") }}
			{{ $seconds = int "0" }}
		{{ else }}
			{{ $seconds = int (strings.TrimLeft "0" (index $times 2)) }}
		{{ end }}
		{{ $convHours := mul $hours 3600 }}
		{{ $convMinutes := mul $minutes 60 }}
		{{ $totalSeconds := add (add $convMinutes $convHours) $seconds }}
		{{ $total = add $total $totalSeconds }}
{{ end }}
{{ $totalHours := int (math.Floor (div $total 3600)) }}
{{ $totalMinutes := int (math.Floor (div $total 60)) }}
{{ $totalSeconds := int (mod $total 60) }}
<p>{{ printf "%02d" $totalHours }}:{{ printf "%02d" $totalMinutes }}:{{printf "%02d" $totalSeconds }}</p>

Again, thank you for guiding me in the right direction!

2 Likes

Looks great! Well done!

Front matter:

durations = ['1h1m1s', '2m2s', '3s']

Template:

{{ $startTime := time.AsTime 0 }}
{{ $endTime := time.AsTime 0 }}
{{ range .Params.durations }}
  {{ $endTime = $endTime.Add (time.ParseDuration .) }}
{{ end }}
{{ $duration := $endTime.Sub $startTime }}

{{ $duration.String }} --> 1h3m6s
5 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.