Subtracting dates formats in bash
I am trying to create a countdown - most likely the hard way. I have it setup like this:
#! /bin/bash
#When to execute command
execute=$(date +"%T" -d "22:30:00")
#Current time
time=$(date +"%T")
#Subtract one from the other.... the below is line 11
math=$(("$execute"-"$time"))
#Repeat until time is 22:30:00
until [ "$math" == "00:00:00" ]; do
echo "Countdown is stopping in $math"
sleep 1
clear
doneThe problem is.... It isn’t working. Here’s the output in the terminal:
/path/to/file/test.sh: line 11: 22:30:00-16:39:22: syntax error in expression (error token is “:30:00-16:39:22”) Countdown is stopping in Firstly, the error message, what’s wrong?
Secondly, the “Countdown is stopping in” message should have the hours, minutes, and seconds that the countdown will stop in. Why doesn’t it? Keep in mind I am not a professional.
32 Answers
The problem is with the statement
math=$(("$execute"-"$time"))Because execute and time contain values in the format %H:%M:%S. But bash's arithmetic expansion can't evaluate time formats.
Instead of %H:%M:%S format, you can convert times into seconds, do the arithmetic and then print in the desired format.
Something like
#!/bin/bash
#When to execute command
execute=$(date +"%s" -d "22:30:00")
time=$(date +"%s")
math=$((execute-time))
if [[ $math -le 0 ]]; then echo "Target time is past already." exit 0
fi
#Repeat until time is 22:30:00
while [[ $math -gt 0 ]]; do printf "Countdown is stopping in %02d:%02d:%02d" $((math/3600)) $(((math/60)%60)) $((math%60)) sleep 1 clear # Reset count down using current time; # An alternative is to decrease 'math' value but that # may be less precise as it doesn't take the loop execution time into account time=$(date +"%s") math=$((execute-time))
done 6 Thanks, @P.P for the answer. Your method worked at first, but stopped working after a reboot.... Also, it didn't stop the cycle - meaning it went into negative numbers and never executed commands afterwards. This is what I ended up doing:
#! /bin/bash
#When to execute command
execute=$(date +"%s" -d "22:30:00")
time=$(date +"%s")
math=$((execute-time))
#Repeat until time is 22:30:00
until [ "$time" == "$execute" ]; do printf "The server will stop in %02d:%02d:%02d" $((math/3600)) $(((math/60)%60)) $((math%60)) sleep 1 clear # Reset count down using current time; # An alternative is to decrease 'math' value but that # may be less precise as it doesn't take the loop execution into account time=$(date +"%s") math=$((execute-time))
if [ "$time" == "$execute" ]; then
break
fi
done
echo "Cycle has ended" 2 More in general
"Zoraya ter Beek, age 29, just died by assisted suicide in the Netherlands. She was physically healthy, but psychologically depressed. It's an abomination that an entire society would actively facilitate, even encourage, someone ending their own life because they had no hope. Th…"