I would like to convert times into seconds aka:
00:24:56 = 25 * 60 56 = 1556
01:00:00 = 1 * 60 * 60 = 3600
I had been using: date -d$element %s
but this of course returns the current date and time in seconds.
CodePudding user response:
Simply specify the starting date of Unix time (also known as "Epoch") in the UTC time zone (shorthand Z
):
time=00:24:56
date -d "1970-01-01 $time Z" %s
# prints 1496
CodePudding user response:
The title says in Bash, so I’m going to assume that no external tools (such as date
) are allowed. At which point I would do something old-fashioned — like a calculation with a base-60 number:
#!/usr/bin/env bash
set -euo pipefail
shopt -s extglob
to_seconds() {
local -a digits
IFS=: digits=($1)
local -air digits=("${digits[@]## (0)}") # else ^0 means octal
local -i i="$((${#digits[@]} - 1))" result=0 order=1
for ((;;)); do
((result = digits[i] * order)) || :
((--i < 0)) && break || :
((order *= 60))
done
echo "$((result))"
}
As a side note, the base#number
integer syntax is easy to find in the Bash man
page, but I have never found a way to (ab)use it nicely. On the other hand, there is always an obvious and ugly way to use that syntax:
#!/usr/bin/env bash
set -euo pipefail
shopt -s extglob
declare -ar DIGITS=(0 1 2 3 4 5 6 7 8 9
a b c d e f g h i j
k l m n o p q r s t
u v w x y z A B C D
E F G H I J K L M N
O P Q R S T U V W X)
to_seconds() {
local -a digits
IFS=: digits=($1)
local -air digits=("${digits[@]## (0)}") # else ^0 means octal
local -i digit
local result=
for digit in "${digits[@]}"; do
result ="${DIGITS[digit]}"
done
echo "$((60#"$result"))" # Magic! Ugliness!
}
Examples:
to_seconds 01:09:09 # 4149
to_seconds 01:11:09 # 4269
to_seconds 23:09:00 # 83340
to_seconds 00:59:59 # 3599
to_seconds 00:09:09 # 549
to_seconds 11:09:09 # 40149
to_seconds 23:59:59 # 86399