¿Es posible formatear fácilmente segundos como un tiempo legible para humanos en bash?
No quiero formatearlo como una fecha, sino como el número de días / horas / minutos, etc.
¿Es posible formatear fácilmente segundos como un tiempo legible para humanos en bash?
No quiero formatearlo como una fecha, sino como el número de días / horas / minutos, etc.
Respuestas:
Puedes usar algo como esto:
function displaytime {
local T=$1
local D=$((T/60/60/24))
local H=$((T/60/60%24))
local M=$((T/60%60))
local S=$((T%60))
(( $D > 0 )) && printf '%d days ' $D
(( $H > 0 )) && printf '%d hours ' $H
(( $M > 0 )) && printf '%d minutes ' $M
(( $D > 0 || $H > 0 || $M > 0 )) && printf 'and '
printf '%d seconds\n' $S
}
Ejemplos:
$ displaytime 11617
3 hours 13 minutes and 37 seconds
$ displaytime 42
42 seconds
$ displaytime 666
11 minutes and 6 seconds
La forma más fácil y limpia es este revestimiento (aquí asumiendo GNU date
):
Si el número de segundos es, diga:
seconds=123456789 # as in one of the answers above
eval "echo $(date -ud "@$seconds" +'$((%s/3600/24)) days %H hours %M minutes %S seconds')"
-> salida: 1428 days 21 hours 33 minutes 09 seconds
+%T
formato de Horas: Minutos: Segundos para que esto date +%T "1970-01-01 + ${seconds} seconds"
llegue21:33:09
El crédito es para Stéphane Giménez, pero si a alguien le gustaría mostrar segundos solo si un período es inferior a un minuto, esta es mi versión modificada que uso (también con pluralización fija):
converts()
{
local t=$1
local d=$((t/60/60/24))
local h=$((t/60/60%24))
local m=$((t/60%60))
local s=$((t%60))
if [[ $d > 0 ]]; then
[[ $d = 1 ]] && echo -n "$d day " || echo -n "$d days "
fi
if [[ $h > 0 ]]; then
[[ $h = 1 ]] && echo -n "$h hour " || echo -n "$h hours "
fi
if [[ $m > 0 ]]; then
[[ $m = 1 ]] && echo -n "$m minute " || echo -n "$m minutes "
fi
if [[ $d = 0 && $h = 0 && $m = 0 ]]; then
[[ $s = 1 ]] && echo -n "$s second" || echo -n "$s seconds"
fi
echo
}
Un ejemplo alternativo en POSIX:
converts(){
t=$1
d=$((t/60/60/24))
h=$((t/60/60%24))
m=$((t/60%60))
s=$((t%60))
if [ $d -gt 0 ]; then
[ $d = 1 ] && printf "%d day " $d || printf "%d days " $d
fi
if [ $h -gt 0 ]; then
[ $h = 1 ] && printf "%d hour " $h || printf "%d hours " $h
fi
if [ $m -gt 0 ]; then
[ $m = 1 ] && printf "%d minute " $m || printf "%d minutes " $m
fi
if [ $d = 0 ] && [ $h = 0 ] && [ $m = 0 ]; then
[ $s = 1 ] && printf "%d second" $s || printf "%d seconds" $s
fi
printf '\n'
}
convert $s
para obtener una salida bonita.
Lo haría así:
$ seconds=123456789; echo $((seconds/86400))" days "$(date -d "1970-01-01 + $seconds seconds" "+%H hours %M minutes %S seconds")
1428 days 21 hours 33 minutes 09 seconds
$
Aquí está el revestimiento de arriba, desglosado para que sea más fácil de entender:
$ seconds=123456789
$ echo $((seconds/86400))" days"\
$(date -d "1970-01-01 + $seconds seconds" "+%H hours %M minutes %S seconds")
En lo anterior, estoy haciendo eco de la salida de otro comando que se ejecuta dentro del $( ... )
subcomando. Ese subcomando hace esto, calcula el número de días (segundos / 86400), luego usa el date
comando en otro subcomando $(date -d ... )
para generar las horas, minutos y segundos para un número determinado de segundos.
Modifiqué la función de tiempo de visualización anterior ... de la siguiente manera:
seconds2time ()
{
T=$1
D=$((T/60/60/24))
H=$((T/60/60%24))
M=$((T/60%60))
S=$((T%60))
if [[ ${D} != 0 ]]
then
printf '%d days %02d:%02d:%02d' $D $H $M $S
else
printf '%02d:%02d:%02d' $H $M $S
fi
}
porque siempre quiero ver HH: MM: SS, incluso si son ceros.
Estoy construyendo sobre la respuesta de atti que me gustó como idea.
Puede hacer esto con el bash incorporado, printf
que tomará los segundos desde la época como argumento. No es necesario bifurcar para correr date
.
Debe configurar la zona horaria en UTC printf
porque formatea la hora en su zona horaria local y obtendrá la respuesta incorrecta si no está en la hora UTC.
$ seconds=123456789
$ TZ=UTC printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1428 days 21 hours 33 minutes 09 seconds
En mi hora local (que actualmente es NZDT - +1300) la respuesta es incorrecta si no configuro la zona horaria
$ seconds=123456789
$ printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1428 days 09 hours 33 minutes 09 seconds
Con y sin configurar la zona horaria
$ seconds=$(( 3600 * 25))
$ printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1 days 13 hours 00 minutes 00 seconds
$ TZ=UTC printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1 days 01 hours 00 minutes 00 seconds
printf
introdujo esta %(datefmt)T
notación comenzando con bash-4.2-alpha.
Aqui uno
secs=378444
echo $(($secs/86400))d $(($(($secs - $secs/86400*86400))/3600))h:$(($(($secs - $secs/86400*86400))%3600/60))m:$(($(($secs - $secs/86400*86400))%60))s
Salida:
4d 9h:7m:24s
date --date '@1005454800'
te da Sun Nov 11 00:00:00 EST 2001
, que es 1005454800 segundos después de la época de Unix. Puede formatear eso con la opción de fecha + FORMATO.