M BUZZ CRAZE NEWS
// general

Subtracting dates formats in bash

By John Parsons

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
done

The 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.

3

2 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

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy