How to sum time using bash?
Solution 1
#!/bin/sh
EPOCH='jan 1 1970'
sum=0
for i in 00:03:34 00:00:35 00:12:34
do
sum="$(date -u -d "$EPOCH $i" +%s) + $sum"
done
echo $sum|bc
date -u -d "jan 1 1970" +%s
gives 0. So date -u -d "jan 1 1970 00:03:34" +%s
gives 214 secs.
Solution 2
Update:
Here is a new implementation that makes use of dc
's "output base." Note that if the total sum is more than 60 hours, this will output four space-separated values instead of three. (And if the total sum is less than one hour, only two space-separated values will be output.)
awk '{print $2}' file.txt | tr : \ | dc -f - -e '60o0ddd[+r60*+r60d**+z1<a]dsaxp'
Input is assumed to be in triples of hour, minute, second, as shown in the question.
Output on the provided input is:
16 43
Original answer:
Let's do this with dc
your Desk Calculator. It's the back-end to bc
, and it's extremely flexible although often considered cryptic.
First, some pre-processing to give the times only, and convert the colons to spaces:
awk '{print $2}' | tr : ' '
We could also do this with Sed:
sed -En -e 's/^.*([0-9][0-9]):([0-9][0-9]):([0-9][0-9]).*$/\1 \2 \3/p'
I'll go with Awk and tr
because it's simpler. Either of the above command produces a clean output in the following format. (I'm using my own example text because I consider it more interesting; it has hours included. Yours will work as well.)
$ cat input
9 39 42
8 04 50
7 49 32
10 01 54
7 19 18
Given times in the above format, run them through the following Sed script and pipe the result into dc
as shown:
sed -e '1s/^/0 /' -e 's/$/ r 60 * + r 60 60 * * + +/' -e '$s/$/ 60 60 * ~ 60 ~ f/' input | dc
(Broken down to reduce sideways scrolling:)
sed <input \
-e '1s/^/0 /' \
-e 's/$/ r 60 * + r 60 60 * * + +/' \
-e '$s/$/ 60 60 * ~ 60 ~ f/' |
dc
The output will be seconds, minutes, hours, in that sequence. (Note this is a reversed sequence.) I'm just learning dc
so this isn't a perfect solution, but I think it's pretty good for a first look at dc
.
Example input and output, pasted directly from my terminal:
$ cat input
9 39 42
8 04 50
7 49 32
10 01 54
7 19 18
$ sed -e '1s/^/0 /' -e 's/$/ r 60 * + r 60 60 * * + +/' -e '$s/$/ 60 60 * ~ 60 ~ f/' input | dc
16
55
42
$
Solution 3
If you cannot (or don't want) use TIMEFORMAT
your just need to transfer time into seconds, then add it together. For example pipe output through:
{
sum=0
while IFS="[ :]" proc_name h m s
do
let sum+=$((60*($m+60*$h)+$s))
done
echo $sum
}
Or if you'd like can exchange last echo
-command by
printf "%02d:%02d:%02d\n" $[sum/3600] $[sum/60] $[sum%60]
Solution 4
Assuming you are using the bash 'time' builtin command, before you run your program, you can export TIMEFORMAT=%0R
. The output will then be in whole seconds addable by awk. More information is available in the 'Shell Variables' section of the bash man page.
Solution 5
Here is my solution - use split()
.
Printing total time in seconds:
awk '{
split($2, tm, ":");
tottm += tm[3] + tm[2] * 60 + tm[1] * 3600;
}
END {
print tottm;
}' ptime
Printing in nice time format:
awk '{
split($2, tm, ":");
secs += tm[3];
mins += tm[2] + int(secs / 60);
hrs += tm[1] + int(mins / 60);
secs %= 60; mins %= 60;
}
END {
printf "%d:%d:%d\n", hrs, mins, secs;
}' ptime
GNU awk also supports strftime, but it will use your current timezone, so results would be confusing.
Related videos on Youtube
je_b
Updated on September 18, 2022Comments
-
je_b almost 2 years
I want to know the total amount of time that a series of processes would take in my computer to decide if I should running there or in a stronger computer. So, i am forecasting the running time of each command. The output looks like:
process1 00:03:34 process2 00:00:35 process3 00:12:34
How can I sum the second column to obtain a total running time? I could try pipping each line through
awk '{sum += $2 } END { print sum }
but this makes no sense as the values are not natural numbers.
-
androidism over 9 yearsDoes seem a little hack-y, but hey, it works in an interesting (sort-of) way.
-
Stéphane Chazelas over 7 yearsYou can call
gawk
withTZ=UTC0 gawk...
to remove the timezone issue. -
Jesse Chisholm over 4 yearsThe minutes should be
$[sum/60%60]
to strip the hours off.