I'm running a bash script on a Github runner that I have no control over. In it, I need to compare timestamps to make certain that the current time is within an accepted timeframe.
I get start and end timestamps with date, and the script should only continue if the current date/time is within those timestamps.
But the server is so locked down that I cannot use TZ=America/Chicago date
- it refuses to let me update TZ or anything else that I was able to find to temporarily set a time zone. I read that the time zone can be set to read-only, so that would be my guess.
What finally worked was this:
now=$(date '+%s' -d "now CST")
startdate=$(date '+%s' -d "$startraw CST")
finishdate=$(date '+%s' -d "$finishraw CST")
if [ $now -ge $startdate ] && [ $now -lt $finishdate ]; then
echo "Current time is allowed"
else
echo "ERROR - current time is not allowed"
fi
$startraw
and $finishraw
are in this format: 03/21/2024 08:00:00
.
I tried inserting America/Chicago
instead of CST
but that could not be parsed, so I used CST
.
Now I had a UTC timestamp that I could compare correctly - until Daylight Savings hit when the current time no longer fit into the start and end time values even when it should.
So I found that there is CDT
which is CST with daylight savings time included (if I understood it correctly).
Except now my results are even more off...
I just ran some test code:
now1=$(date '+%s' -d "now CST")
now2=$(date '+%s' -d "now CDT")
echo "Human readable times:"
echo "Now CST: $(date -d @$now1)"
echo "Now CDT: $(date -d @$now2)"
It is currently 8:11am CST [edit: CST in colloquial terms, not in computer terms]. This should be 1:11pm UTC according to Google.
The output when I convert the timestamp back into human readable:
Now CST: Thu Mar 21 19:11:44 UTC 2024
Now CDT: Thu Mar 21 18:11:44 UTC 2024
So that is 7pm and 6pm instead of the expected 1pm.
The server should be set to use UTC since my test code resulted in an output with "UTC" in it.
I guess it is possible that the server they are using is out of date on its time zone definitions, but still, there shouldn't be a 5 or 6 hour difference between actual UTC and what the server is giving me.
The CST part worked 2 weeks ago (i.e. before DST hit).
It is possible that the server owners made changes to their time zone settings, but that does not explain why the debug output returns UTC.
Can someone help me figure out what is going on here and how to make this work with daylight savings time?
Thanks!
It is possible that the server owners made changes to their time zone settings, but that does not explain why the debug output returns UTC.
More likely, the change to DST in your area is what produced the breakage.
I just ran some test code:
now1=$(date '+%s' -d "now CST") now2=$(date '+%s' -d "now CDT") echo "Human readable times:" echo "Now CST: $(date -d @$now1)" echo "Now CDT: $(date -d @$now2)"
It is currently 8:11am CST [edit: CST in colloquial terms, not in computer terms]. This should be 1:11pm UTC according to Google.
The output when I convert the timestamp back into human readable:
Now CST: Thu Mar 21 19:11:44 UTC 2024 Now CDT: Thu Mar 21 18:11:44 UTC 2024
So that is 7pm and 6pm instead of the expected 1pm.
The command ...
date '+%s' -d "now CDT"
... says "take the current local time, reinterpret it as being expressed in CDT, and print the corresponding timestamp." If that makes you scratch your head, then it may make more sense if you think about what you would expect when an explicit time is specified instead of now
; for example, 13:01:00 EDT
.
Such timestamps are defined relative to UTC, however, regardless of the local time zone, so the command ...
date -d @$now2
... says "expand variable now2
, interpret the result as a timestamp (relative to UTC, regardless of local time zone), and print the resulting date and time in the default format." The default format uses the local time zone, which in your case happens to be UTC.
Chaining those together produces what the time is / was / will be in the local time zone when the CDT time is what the local time is now. That's a bit of a mouthful, so here's a breakdown:
date
command at 13:11:44 according to the server's local timedate
command, and asked for it to be formatted in the default formatThat's not what you wanted, of course.
Of course, you can, and I guess did, work with that by expressing your start and end times in UTC or in the server's local time zone, or with a fixed offset from one of those. But if the start and end times relevant to you are expressed in the local time of an area that observes different DST behavior than your time reference does than that breaks when the two time references diverge.
As far as I am aware, the only way to request date
to format dates in a different zone than is specified in /etc/localtime
is to use the TZ
environment variable. The conventional way to do that is to specify it as a command-line prefix:
TZ=America/Chicago date
That may not work if your shell is configured to prevent TZ
being modified, and in that case it is worth trying to use env
to bypass the shell for controlling date
's environment:
env TZ=America/Chicago date
In particular, that still works for me in a Bash shell in which I have used declare -r TZ
to mark the TZ
variable read-only.
If using env
does not do the job then you probably need to explore alternatives to the date
command. For example, if you can run Python scripts then Python's rather more flexible date / time utilities could be brought to bear.