Date comparison & timezone offset help

Can someone help me with this date comparison?

Is it possible to work out if this is before or after now?

Tue Oct 13 2020 10:00 AM PT

eg {{ if gt .date now }}


Anyway interested there is an excellent explanation of timezones with Hugo at the bottom of this thread.

How accurate does it have to be? Can we round down to the nearest day, or do you need hour:min granularity?

convert to unix time.

{{ if gt .Date.Unix now.Unix }}

I tried the unix timestamp conversion but I’m getting the following error:

at <$date.Unix>: can’t evaluate field Unix in type string

I think the issue is my date field is coming from a data file so I guess Hugo is considering it a string and not a date. How do I make sure it gets converted?

Here’s the data file:

data:
- Tue Jul 21 2020 10:00 AM PT
- Tue Aug 11 2020 10:00 AM PT
- Tue Sep 15 2020 10:00 AM PT
- Tue Oct 13 2020 10:00 AM PT

Here’s my code:

{{ $datafile := index $fields “data” }}
{{ range $datafile }}
{{ $date := . }}
{{ if gt $date.Unix now.Unix }}
{{ . }}
{{ end }}
{{ end }}

Try

{{ if gt (time .date) now }}

Partially worked, no error but now the condition never evaluates to true.

Back to my original question:

Nearest day works.

You have to wrangle the date from your external source into a format understood by go. The partial referenced below uses an inline partial, so you’ll need Hugo 0.74.1.

content/foo,md:

{{< test "Tue Oct 13 2020 10:12 PM PT" >}}

layouts/shortcodes/test.html:

{{- $input := "" -}}
{{- with .Get 0 -}}
  {{- $input = . -}}
{{- else -}}
  {{- $msg1 := printf "The '%s' shortcode requires one positional parameter, a timestamp" .Name -}}
  {{- $msg2 := printf "formatted as follows: Tue Oct 13 2020 10:12 PM PT. See %s" .Position -}}
  {{- errorf "%s %s" $msg1 $msg2 -}}
{{- end -}}

{{- $timestamp := partial "convert-date.html" $input -}}

{{- $str_timestamp := $timestamp.Format "2006-01-02T15:04:05-07:00" -}}
{{- $str_now := now.Format "2006-01-02T15:04:05-07:00" -}}

<pre>
Input:     {{ $input }} (time zone will be ignored)<br>
Converted: {{ $str_timestamp }}<br>
Now:       {{ $str_now }}
</pre>

<br>

{{- if gt $timestamp now -}}
<pre>The input date is greater than now.</pre>
{{- else -}}
<pre>The input date is less than or equal to now.</pre>
{{- end -}}
</p>

layouts/partials/convert-date.html:

{{/*
@param string timestamp
  Example: Tue Oct 13 2020 10:12 PM PT

@returns time converted_timestamp
  Example: 2020-10-13T22:12:00

The time zone is ignored.
*/}}
{{- $time_parts := split . " " -}}

{{- $year := index $time_parts 3 -}}
{{- $month := partial "get-month-number" (index $time_parts 1) -}}
{{- $day := index $time_parts 2 -}}
{{- $hour := index (split (index $time_parts 4) ":") 0 -}}
{{- $min := index (split (index $time_parts 4) ":") 1 -}}
{{- $sec := "00" -}}
{{- $period := index $time_parts 5 -}}
{{- $tz := index $time_parts 6 -}}
{{- $offset := "00:00" }}

{{- if eq (lower (index $time_parts 5)) "pm" -}}
  {{ $hour = string (add (int $hour) 12) }}
{{- end -}}

{{- $converted_timestamp := printf "%s-%s-%sT%s:%s:%s-%s" $year $month $day $hour $min $sec $offset -}}

{{- return time $converted_timestamp  }}

{{/*
@param string month_name
  Examples: mar, march, Mar, March

@returns string month_number
  Example: 03
*/}}
{{- define "partials/get-month-number" -}}
  {{- $months := dict -}}

  {{- $months = merge $months (dict "jan" "01") -}}
  {{- $months = merge $months (dict "feb" "02") -}}
  {{- $months = merge $months (dict "mar" "03") -}}
  {{- $months = merge $months (dict "apr" "04") -}}
  {{- $months = merge $months (dict "may" "05") -}}
  {{- $months = merge $months (dict "jun" "06") -}}
  {{- $months = merge $months (dict "jul" "07") -}}
  {{- $months = merge $months (dict "aug" "08") -}}
  {{- $months = merge $months (dict "sep" "09") -}}
  {{- $months = merge $months (dict "oct" "10") -}}
  {{- $months = merge $months (dict "nov" "11") -}}
  {{- $months = merge $months (dict "dec" "12") -}}

  {{- $month_name := substr . 0 3 | lower -}}
  {{- $month_number := index $months $month_name -}}

  {{- return $month_number -}}
{{- end -}}

OK let me take a look through. I do have the option of changing the date in the date file to some other format if that would help Go view it as a date object?

Yes, it would. For example:

2020-07-17T11:26:14-04:00

That did the trick, my condition is now evaluating correctly

For reference:

Data file:

data:
- 2020-07-21T10:00:00-08:00
- 2020-08-11T10:00:00-08:00
- 2020-09-15T10:00:00-08:00
- 2020-10-13T10:00:00-08:00

Code:

{{ if gt (time .data ) now }}

Only issue I have now is formatting the date back to what I need:

This: {{ dateFormat “Tue Jul 21 2020 10:00 AM PT” . date}}

Outputs: Tue Jul 118 11110 80:00 AM PT

dateFormat "Mon Jan 2 2006 3:04 PM MST"

Note that “PT” is not a valid time zone. On the west coast of the United States, the time zone is either PST or PDT.

Thank you, that mostly did it, but the timezone isn’t getting translated:

Tue Aug 11 2020 10:00 AM -0800

What is the current offset of your system? I suspect it is not -08:00. Please confirm.

I’m just testing locally, How would I find that out?

On Linux:

date -Iseconds

Ahh, sorry you meant my machine. I’m GMT -6 currently.

I actually don’t know how Hugo processes timezones. If you have any pointers, appreciated.

Short Answer

If you want to ignore the offset in your dates, and always print PT, do this:

dateFormat "Mon Jan 2 2006 3:04 PM PT"

Medium Answer

Don’t display the time zone abbreviation. Display the offset instead. Why? Because time zone abbreviations are essentially useless.

dateFormat "Mon Jan 2 2006 15:04 -07:00"

Long Answer

There is a N:N relationship between time zone abbreviations and offsets. For example:

Different offsets with the same time zone abbreviation:

Time Zone Abbreviation Description Offset
CST Central Standard Time (North America) -06:00
CST China Standard Time +08:00
CST Cuba Standard Time -05:00

Different time zone abbreviations with the same offset:

Offset Description Time Zone Abbreviation
-06:00 Central Standard Time (North America) CST
-06:00 Mountain Daylight Time (North America) MDT
-06:00 Easter Island Standard Time EAST
-06:00 Galápagos Time GALT

So, when the timestamp is 2020-07-17T12:49:12-04:00, which time zone abbreviation should be displayed? It depends on where you are. Similarly, if you say you eat dinner at 5 PM CST, I have no idea when you actually eat dinner.

With Hugo, if you use the Mon Jan 2 2006 3:04 PM MST format string:

  • When the offset of the date to be formatted is the same as your local offset, the local time zone abbreviation for the offset is displayed, based on the TZ environment variable on your machine. If you change the TZ environment variable on your machine to America/Los_Angeles and rebuild the site, you will get different results.
  • When the offset of the date to be formatted is different than your local offset, we have no idea what time zone abbreviation to display, so we display the offset instead.

So what to do?

Don’t display the time zone abbreviation. Display the offset instead.

References: