Like in sleep: sleep 1h 30m 50s
. But ideally with even more flexibility like in time calculator with support time corrections with minus sign.
Examples:
time2seconds (t2s) 1h30m50s # basic case - result should be: 5450 seconds
t2s 1h30m-30s # with correction by minus sign - result should be: 5370 seconds
t2s 1h-5s # result should be 3595 seconds
t2s 15m*3 # it might also be convenient to use multiplication sign - result should be: 2700 seconds
Below is my own script with draft solution but it needs to be rewritten to have more performance respect (as described by markp-fuso now it creates huge amount of subshells)
Implementation below in time2seconds
function.
Usages examples:
time2seconds 1h30m50s debug # 5450
t2s 1h30m-30s d # 5370
t2s 1h-5s d # 3595
t2s 15m*3 d # 2700
log(){
msg_content="$1"
print_to_console=${2:-"print_to_console"}
msg="`date +"%Y-%m-%dT%H:%M:%S"` - $msg_content"
if [ $print_to_console = "print_to_console" ]; then
echo -e "$msg"
fi
}
FUNCTION_RESULT= # global var, used for functions to return values
alias t2s="time2seconds"
# Calculates for entered time amount of seconds
# Supported formats:
# 1d1h1m1s
# hh:mm:ss (for "backwards compatibility", for those who got used to this format)
# Any parts can be omitted. Examples of valid input:
# 1h, 1h30m, 1d5s, 30m, 100h, 200m, 300s, 59 (seconds), 1m30 (1m30s), 1h1h1h (3h)
# 102:30:59, 2:3:59, 3:59, 100:200:300, 500 (seconds)
# For 1d1h1m1s format supports correction of input by means of calculations like:
# 1h-1m (result is 59m), 1d-1h30m (result is 22h30m), 15m*3 (result is 45m)
# To debug time to seconds conversion algorithm (print detailed output to console):
# time2seconds 1d-1h30m+5 debug # test run
# t2s 1d10h30s-1h1m d # alternative test run with aliases
function time2seconds() {
start_time=$(date +%s%3N)
time="${1}"
out="${2:-"do_not_print_to_console"}"
if [ "$out" = "debug" ] || [ "$out" = "d" ] || [ "$out" = "print" ]; then
out="print_to_console"
fi
case "$time" in
*d*|*h*|*m*|*s*)
log "handling several cases for d, h, m, s tokens" $out
time=$(echo "$time" | sed -E 's/([[:digit:]]+)([^[:alnum:]])/\1s\2/g')
log "time1, added missing s tokens: $time" $out
time=$(echo "$time" | sed -E 's/([[:digit:]]+)$/\1s/')
log "time2, added missing s token to the very end: $time" $out
time=$(echo "$time" | sed -E 's/([[:alnum:]]+)/\(\1\)/g')
log "time3, added round braces (): $time" $out
time=$(echo "$time" | sed -E 's/([[:digit:]]+)d/+\1*24*3600;/g')
log "time4, days to seconds: $time" $out
time=$(echo "$time" | sed -E 's/([[:digit:]]+)h/+\1*3600;/g')
log "time5, hours to seconds: $time" $out
time=$(echo "$time" | sed -E 's/([[:digit:]]+)m/+\1*60;/g')
log "time6, mins to seconds: $time" $out
time=$(echo "$time" | sed -E 's/([[:digit:]]+)s/+\1;/g')
log "time7, seconds to seconds: $time" $out
time=$(echo "$time" | sed -E 's/;//g')
log "time8, semicolon ; delimeter removed: $time" $out
time=$(echo "$time" | sed -E 's/\(\+/(/g')
log "time9, leading plus signs removed: $time" $out
calculated_seconds=$(echo "$time" | bc)
;;
*)
log "handling case with colon (:)" $out
calculated_seconds=$(echo "$time" | sed -E 's/(.*):(.+):(.+)/\1*3600+\2*60+\3/;s/(.+):(.+)/\1*60+\2/' | bc)
;;
*)
esac
log "calculated_seconds by bc: $calculated_seconds" $out
end_time=$(date +%s%3N)
duration_ms=$((end_time - start_time))
log "time2seconds execution time in ms: $duration_ms" $out
FUNCTION_RESULT="$calculated_seconds" # global var is used to return result from function
}
Related questions: