Range sort by dates has inconsistent behavior

We’ve been encountering a tough to reproduce bug with some of our Hugo code. This occurs in our existing codebase as well as the new theme we are developing (but I’ll refer only to the new code).

We have a set of datafiles that represent different events; we call a range of these events, sorted by the parameter “startdate”, and then display them in that order.

Sometimes, for reasons we cannot understand, they will display out of order. Running hugo again on the same content files will fix the issue.

Here is one snippet of code that uses this https://github.com/devopsdays/devopsdays-theme/blob/master/layouts/index.html:

    {{ $.Scratch.Add "i" 1 }}
    <div class="row">
        {{- range sort $.Site.Data.events "startdate" -}}
        {{- if .startdate -}}
        {{- if ge (dateFormat "2006-01-02" .enddate) (dateFormat "2006-01-02" ($.Now.Format "2006-01-02")) -}}
        {{ $.Scratch.Set "city" .city }}
        {{ $.Scratch.Set "year" .year }}
        {{ $.Scratch.Set "logo" "unset" }}
        <div class="col-md-3 homepage-grid-col">
            {{ $.Scratch.Set "subdir" .name }}
            {{ $.Scratch.Set "contentdir" (printf "static/events/%s/" ($.Scratch.Get "subdir")) }}
            {{ if (where (readDir "static/events") "Name" ($.Scratch.Get "subdir"))}}
                {{if (where (readDir ($.Scratch.Get "contentdir")) "Name" "logo-square.jpg") }}
                    <a href="/events/{{ .name }}"><img src="/events/{{ .name }}/logo-square.jpg" class="img-fluid" alt="DevOpsDays {{ .city }}"/></a>
                    {{ $.Scratch.Set "logo" "set" }}
                {{ end }}
            {{ end }}
            {{ if ne ($.Scratch.Get "logo") "set" }}
                <a href="/events/{{ .name }}"><img src="/img/event-logo-square.jpg" class="img-fluid" alt="DevOpsDays {{ .city }}"/></a>
                {{- end -}}
                <br/>
                <span class="homepage-grid-date">
                    {{- dateFormat "Jan 2" .startdate -}}
                    &nbsp;-&nbsp;
                    {{-  dateFormat "Jan 2, 2006" .enddate -}}<br/>
                </span>
                <span class="homepage-grid-city">
                    <a href="/events/{{ .name }}">{{ .city }}</a>
                </span>
            </div>
            {{- if modBool ($.Scratch.Get "i") 4 -}}
        </div>
        <div class="row">
            {{- end -}}
            {{ $.Scratch.Add "i" 1 }}
            {{- end -}}
            {{- end -}}
            {{- end -}}

And the other - https://github.com/devopsdays/devopsdays-theme/blob/master/layouts/partials/future.html:

{{- range sort $.Site.Data.events "startdate" -}}
  {{- if .startdate -}}
    {{- if ge (dateFormat "2006-01-02" .enddate) (dateFormat "2006-01-02" ($.Now.Format "2006-01-02")) -}}
      {{- if ne ($.Scratch.Get "year") (dateFormat "2006" .startdate) -}}
        {{- $.Scratch.Set "year" (dateFormat "2006" .startdate) -}}
        {{- $.Scratch.Set "year-displayed" "false" -}}
      {{- end -}}
      {{- if ne ($.Scratch.Get "month") (dateFormat "January" .startdate ) -}}
        {{- $.Scratch.Set "month" (dateFormat "January" .startdate ) -}}
        {{- $.Scratch.Set "month-displayed" "false" -}}
<br />
      {{- end -}}
      {{- if ne ($.Scratch.Get "year-displayed") "true" -}}
        <h3 class="left-nav-year">{{ dateFormat "2006" .startdate }}</h3>
        {{- $.Scratch.Set "year-displayed" "true" -}}
      {{- end -}}
      {{- if ne ($.Scratch.Get "month-displayed") "true" -}}
        <h4 class="left-nav-months">{{ dateFormat "January" .startdate }}</h4>
        {{- $.Scratch.Set "month-displayed" "true" -}}
      {{- end -}}
      {{- if ne .startdate .enddate }}
      <a href = "/events/{{ .name }}/" class = "left-nav-event">
        {{ dateFormat "Jan 2" .startdate }} - {{ dateFormat "Jan 2" .enddate }}
        {{ .city }}
      </a><br />
      {{- else -}}
      <a href = "/events/{{ .name }}/" class = "left-nav-event">
        {{ dateFormat "Jan 2" .startdate }}
        {{ .city }}
      </a><br />
      {{- end -}}
    {{- end -}}
  {{- end -}}
{{- end -}}
<h3 class="left-nav-year">TBD</h3>
{{- range $.Site.Data.events -}}
  {{- if not .startdate -}}
    <a href = "/events/{{ .name }}/" class = "left-nav-event">{{ .city }}</a><br />
  {{- end -}}
{{- end -}}

Some more details can be found in our tracking issue

Any ideas? Are we doing something terribly foolish?

This is stab in the dark, but does it have anything to do with the ge operator and dateFormat? That is, is it comparing a string vs int? Then again, if it fixes itself at build time (i.e., when running hugo), I’m out of ideas…

Well, we do convert them to dates before doing the ge, so that seems unlikely. And like you said, it’s inconsistent and when it works we don’t touch anything. Weird.

I did notice that we convert the value of “Now” twice, but I’m not sure why that would matter…