Frontier Software

Date

The primary reason I’m using bash rather than some programing language is to get easy access to GNU’s powerful date program. It automagically reads most text descriptions of dates and can then translate them to what I want, which is ISO 8601 as specified by schema.org.

Getting dates right has been a constant source of bugs — it took me a while to figure that because my development machine is set to my local time, “Africa/Johannesburg” and my server to “UTC”, joeblog.co.za was showing all events 2 hours early.

GNU’s date is a very complex piece of software which speaks its own DSL, only a fraction of which I understand.

zatime function

Developing this came after quiete an eduation curve. It started with the old but it works on my machine problem where joeblog.co.za would have the correct times on my development computer, but then all the times would be 2 hours earlier on the server.

It turned out the TZ environment variable was set to my localtime (Johannesburg) on my laptopt and UTC on my server (as is considered good practice). Changing the value of an environment variable at the start of a line changes it for just that line.

TZ=Africa/Johannesburg date -d "$1" +%Y-%m-%dT%H:%M:%S+02:00

The next mistake I made in an early attempt was instead of simply echoing the result, I passed the name of an associtive array in the structure I’m trying to manipulate and had the function set the value.

Programming like that in Bash turns out to be riddled with problems because of its tendency to forget variables set in subshells.

This also lead me to some enlightenment on “function or standalone script?”. Even though zatime is a oneliner (which grew as I added options to give default endDates), it’s an ideal function because it consumes and produces text.

My initial attempts at TZ=Africa/Johannesburg date -d "11 Dec 2023 09:00 +4 hours" +%Y-%m-%dT%H:%M:%S+02:00 produced 2023-12-11T08:00:00+02:00 instead of the desired 2023-12-11T13:00:00+02:00. It seems that to get date arithmetic to work, first convert to ISO 8601, then only use in arithmetic.

#!/bin/bash

ExampleGroup 'zatime function tests'

  Example 'convert "11 Dec 2023 09:00"'
    When call zatime "11 Dec 2023 09:00"
    The output should equal '2023-12-11T09:00:00+02:00'
    The status should be success
    The error should be blank
  End

  Example 'convert "11 Dec 2023 09:00 + 4 hours" has to be done in 2 steps'
    d="$(zatime '11 Dec 2023 09:00')"
    When call zatime "$d +4 hours"
    The output should equal '2023-12-11T13:00:00+02:00'
    The status should be success
    The error should be blank
  End

End
ExampleGroup 'date examples'

  ExampleGroup '"2023-12-12T07:30:00Z" format as supplied by quicket needs TZ set correctly'

    Example '"2023-12-12T07:30:00Z" with TZ=UTC as on server'
      When call echo $(TZ=UTC date -d "2023-12-12T07:30:00Z" +%Y-%m-%dT%H:%M:%S+02:00)
      The output should equal '2023-12-12T07:30:00+02:00'
      The status should be success
      The error should be blank
    End

    Example '"2023-12-12T07:30:00Z" with TZ=Africa/Johannesburg as on laptop'
      When call echo $(TZ=Africa/Johannesburg date -d "2023-12-12T07:30:00Z" +%Y-%m-%dT%H:%M:%S+02:00)
      The output should equal '2023-12-12T09:30:00+02:00'
      The status should be success
      The error should be blank
    End

  End

  Example '"2023-12-12T09:30:00+02:00" should remain unchanged'
    When call echo $(TZ=Africa/Johannesburg date -d "2023-12-12T09:30:00+02:00" +%Y-%m-%dT%H:%M:%S+02:00)
    The output should equal '2023-12-12T09:30:00+02:00'
    The status should be success
    The error should be blank
  End

  ExampleGroup '"11 Dec 2023 09:00" format as supplied by webtickets ignores TZ'

    Example '"11 Dec 2023 09:00" with unset TZ'
      When call date -d "11 Dec 2023 09:00" +%Y-%m-%dT%H:%M:%S+02:00
      The output should equal '2023-12-11T09:00:00+02:00'
      The status should be success
      The error should be blank
    End

    Example '"11 Dec 2023 09:00" with TZ=UTC as on server'
      When call echo $(TZ=UTC date -d "11 Dec 2023 09:00" +%Y-%m-%dT%H:%M:%S+02:00)
      The output should equal '2023-12-11T09:00:00+02:00'
      The status should be success
      The error should be blank
    End

    Example '"11 Dec 2023 09:00" with TZ=Africa/Johannesburg as on laptop'
      When call echo $(TZ=Africa/Johannesburg date -d "11 Dec 2023 09:00" +%Y-%m-%dT%H:%M:%S+02:00)
      The output should equal '2023-12-11T09:00:00+02:00'
      The status should be success
      The error should be blank
    End

    Example '"11 Dec 2023" ie missing time will default to midnight'
      When call date -d "11 Dec 2023" +%Y-%m-%dT%H:%M:%S+02:00
      The output should equal '2023-12-11T00:00:00+02:00'
      The status should be success
      The error should be blank
    End

  End

  ExampleGroup 'Webtickets formats that date cannot process'

    Example '"09 & 12 December 2023" needs to be rewritten for date'
      When call date -d "09 & 12 December 2023" +%Y-%m-%dT%H:%M:%S+02:00
      The status should be failure
      The error should be present
    End

    Example '"12th - 13th December 2023" needs to be rewritten for date'
      When call date -d "12th - 13th December 2023" +%Y-%m-%dT%H:%M:%S+02:00
      The status should be failure
      The error should be present
    End

    Example '"15th December 2023" needs to be rewritten for date'
      When call date -d "15th December 2023" +%Y-%m-%dT%H:%M:%S+02:00
      The status should be failure
      The error should be present
    End

  End

End