Cómo calcular la diferencia de tiempo en bash script?
Imprimo la hora de inicio y finalización usando date +"%T"
, lo que resulta en algo como:
10:33:56
10:36:10
¿Cómo podría calcular e imprimir la diferencia entre estos dos?
Me gustaría obtener algo como:
2m 14s
18 answers
Bash tiene una útil variable incorporada SECONDS
que rastrea el número de segundos que han pasado desde que se inició el shell. Esta variable conserva sus propiedades cuando se asigna a, y el valor devuelto después de la asignación es el número de segundos desde la asignación más el valor asignado.
Por lo tanto, solo puede establecer SECONDS
a 0 antes de comenzar el evento cronometrado, simplemente lea SECONDS
después del evento y haga la aritmética del tiempo antes de mostrarlo.
SECONDS=0
# do some work
duration=$SECONDS
echo "$(($duration / 60)) minutes and $(($duration % 60)) seconds elapsed."
Ya que esta solución no depende de date +%s
(que es una extensión GNU), es portable a todos los sistemas soportados por Bash.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-12 01:12:25
Segundos
Para medir el tiempo transcurrido (en segundos) necesitamos: {[42]]}
- un entero que representa la cuenta de segundos transcurridos y
- una forma de convertir dicho entero a un formato utilizable.
Un valor entero de segundos transcurridos:
-
Hay dos formas internas de bash para encontrar un valor entero para el número de segundos transcurridos:
-
Bash segundos variables (si SEGUNDOS no está configurado pierde su especial propiedad).
-
Establecer el valor de SEGUNDOS en 0:
SECONDS=0 sleep 1 # Process to execute elapsedseconds=$SECONDS
-
Almacenando el valor de la variable
SECONDS
al inicio:a=$SECONDS sleep 1 # Process to execute elapsedseconds=$(( SECONDS - a ))
-
-
Opción Bash printf
%(datefmt)T
:a="$(TZ=UTC0 printf '%(%s)T\n' '-1')" ### `-1` is the current time sleep 1 ### Process to execute elapsedseconds=$(( $(TZ=UTC0 printf '%(%s)T\n' '-1') - a ))
-
Convertir dicho entero a un formato utilizable
El bash interno printf
puede hacer eso directamente: {[42]]}
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' 12345
03:25:45
Del mismo modo
$ elapsedseconds=$((12*60+34))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
00:12:34
pero esto fallará por duraciones de más de 24 horas, ya que en realidad imprimimos una hora de wallclock, no realmente una duración:
$ hours=30;mins=12;secs=24
$ elapsedseconds=$(( ((($hours*60)+$mins)*60)+$secs ))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
06:12:24
Para los amantes de los detalles, de bash-hackers.org :
%(FORMAT)T
muestra la cadena de fecha y hora resultante de usar FORMAT como una cadena de formato parastrftime(3)
. El argumento asociado es el número de segundos desde Época, o -1 (hora actual) o -2 (shell tiempo de inicio). Si no se proporciona ningún argumento correspondiente, el actual el tiempo se utiliza como predeterminado.
Así que es posible que desee llamar a textifyDuration $elpasedseconds
donde textifyDuration
es otra implementación de la impresión de duración:
textifyDuration() {
local duration=$1
local shiff=$duration
local secs=$((shiff % 60)); shiff=$((shiff / 60));
local mins=$((shiff % 60)); shiff=$((shiff / 60));
local hours=$shiff
local splur; if [ $secs -eq 1 ]; then splur=''; else splur='s'; fi
local mplur; if [ $mins -eq 1 ]; then mplur=''; else mplur='s'; fi
local hplur; if [ $hours -eq 1 ]; then hplur=''; else hplur='s'; fi
if [[ $hours -gt 0 ]]; then
txt="$hours hour$hplur, $mins minute$mplur, $secs second$splur"
elif [[ $mins -gt 0 ]]; then
txt="$mins minute$mplur, $secs second$splur"
else
txt="$secs second$splur"
fi
echo "$txt (from $duration seconds)"
}
GNU date.
Para obtener tiempo formalizado debemos usar una herramienta externa (GNU date) de varias maneras para obtener hasta casi un año de duración e incluyendo nanosegundos.
Math inside date.
No hay necesidad de aritmética externa, hazlo todo en un solo paso dentro date
:
date -u -d "0 $FinalDate seconds - $StartDate seconds" +"%H:%M:%S"
Sí, hay un 0
cero en el cadena de órdenes. Es necesario.
Eso es asumiendo que podría cambiar el comando date +"%T"
a un comando date +"%s"
para que los valores se almacenen (impriman) en segundos.
Tenga en cuenta que el comando está limitado a:
- Valores positivos de
$StartDate
y$FinalDate
segundos. - El valor en
$FinalDate
es mayor (más tarde en el tiempo) que$StartDate
. - Diferencia horaria inferior a 24 horas.
- Acepta un formato de salida con Horas, Minutos y Segundos. Muy fácil de cambio.
- Es aceptable usar-u UTC times. Para evitar correcciones" DST " y hora local.
Si debe usar la cadena 10:33:56
, bueno, simplemente conviértala en segundos,
además, la palabra segundos podría abreviarse como sec:
string1="10:33:56"
string2="10:36:10"
StartDate=$(date -u -d "$string1" +"%s")
FinalDate=$(date -u -d "$string2" +"%s")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S"
Tenga en cuenta que la conversión de segundos de tiempo (como se presenta anteriormente) es relativa al inicio de "este" día (Hoy).
El concepto podría extenderse a nanosegundos, como esto:
string1="10:33:56.5400022"
string2="10:36:10.8800056"
StartDate=$(date -u -d "$string1" +"%s.%N")
FinalDate=$(date -u -d "$string2" +"%s.%N")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S.%N"
Si se requiere calcular diferencias de tiempo más largas (hasta 364 días), debemos usar el inicio de (algún) año como referencia y el valor de formato %j
(el número de día en el año):
Similar a:
string1="+10 days 10:33:56.5400022"
string2="+35 days 10:36:10.8800056"
StartDate=$(date -u -d "2000/1/1 $string1" +"%s.%N")
FinalDate=$(date -u -d "2000/1/1 $string2" +"%s.%N")
date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N"
Output:
026 days 00:02:14.340003400
Tristemente, en este caso, necesitamos restar manualmente 1
UNO del número de días.
El comando date visualiza el primer día del año como 1.
No es tan difícil ...
a=( $(date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N") )
a[0]=$((10#${a[0]}-1)); echo "${a[@]}"
El uso de largo número de segundos es válido y documentada here:
https://www.gnu.org/software/coreutils/manual/html_node/Examples-of-date.html#Examples-of-date
Fecha de Busybox
Una herramienta utilizada en dispositivos más pequeños (un ejecutable muy pequeño para instalar): Busybox.
O bien hacer un enlace a busybox llamado fecha:
$ ln -s /bin/busybox date
Utilícelo entonces llamando a este date
(colóquelo en un directorio PATH included).
O hacer un alias como:
$ alias date='busybox date'
La fecha de Busybox tiene un buena opción: - D para recibir el formato del tiempo de entrada. Eso abre una gran cantidad de formatos para ser utilizados como tiempo. Usando la opción-D podemos convertir la hora 10:33:56 directamente:
date -D "%H:%M:%S" -d "10:33:56" +"%Y.%m.%d-%H:%M:%S"
Y como se puede ver en la salida del Comando anterior, se asume que el día es "hoy". Para obtener la hora que comienza en epoch:
$ string1="10:33:56"
$ date -u -D "%Y.%m.%d-%H:%M:%S" -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S"
1970.01.01-10:33:56
Busybox date puede incluso recibir la hora (en el formato anterior) sin-D:
$ date -u -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S"
1970.01.01-10:33:56
Y el formato de salida podría incluso ser segundos desde época.
$ date -u -d "1970.01.01-$string1" +"%s"
52436
Para ambas veces, y un poco de matemáticas bash (busybox no puede hacer las matemáticas, todavía):
string1="10:33:56"
string2="10:36:10"
t1=$(date -u -d "1970.01.01-$string1" +"%s")
t2=$(date -u -d "1970.01.01-$string2" +"%s")
echo $(( t2 - t1 ))
O formateado:
$ date -u -D "%s" -d "$(( t2 - t1 ))" +"%H:%M:%S"
00:02:14
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-03 09:13:13
Así es como lo hice:
START=$(date +%s);
sleep 1; # Your stuff
END=$(date +%s);
echo $((END-START)) | awk '{print int($1/60)":"int($1%60)}'
Realmente simple, tome el número de segundos al principio, luego tome el número de segundos al final e imprima la diferencia en minutos:segundos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-27 17:45:26
Otra opción es usar datediff
desde dateutils
(http://www.fresse.org/dateutils/#datediff):
$ datediff 10:33:56 10:36:10
134s
$ datediff 10:33:56 10:36:10 -f%H:%M:%S
0:2:14
$ datediff 10:33:56 10:36:10 -f%0H:%0M:%0S
00:02:14
También puedes usar gawk
. mawk
1.3.4 también tiene strftime
y mktime
pero las versiones anteriores de mawk
y nawk
no lo hacen.
$ TZ=UTC0 awk 'BEGIN{print strftime("%T",mktime("1970 1 1 10 36 10")-mktime("1970 1 1 10 33 56"))}'
00:02:14
O aquí hay otra forma de hacerlo con GNU date
:
$ date -ud@$(($(date -ud'1970-01-01 10:36:10' +%s)-$(date -ud'1970-01-01 10:33:56' +%s))) +%T
00:02:14
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-08 02:36:31
Me gustaría proponer otra forma de evitar recordar date
comando. Puede ser útil en caso de que ya haya recopilado marcas de tiempo en formato de fecha %T
:
ts_get_sec()
{
read -r h m s <<< $(echo $1 | tr ':' ' ' )
echo $(((h*60*60)+(m*60)+s))
}
start_ts=10:33:56
stop_ts=10:36:10
START=$(ts_get_sec $start_ts)
STOP=$(ts_get_sec $stop_ts)
DIFF=$((STOP-START))
echo "$((DIFF/60))m $((DIFF%60))s"
Incluso podemos manejar milisegundos de la misma manera.
ts_get_msec()
{
read -r h m s ms <<< $(echo $1 | tr '.:' ' ' )
echo $(((h*60*60*1000)+(m*60*1000)+(s*1000)+ms))
}
start_ts=10:33:56.104
stop_ts=10:36:10.102
START=$(ts_get_msec $start_ts)
STOP=$(ts_get_msec $stop_ts)
DIFF=$((STOP-START))
min=$((DIFF/(60*1000)))
sec=$(((DIFF%(60*1000))/1000))
ms=$(((DIFF%(60*1000))%1000))
echo "${min}:${sec}.$ms"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-21 17:00:52
Aquí hay algo de magia:
time1=14:30
time2=$( date +%H:%M ) # 16:00
diff=$( echo "$time2 - $time1" | sed 's%:%+(1/60)*%g' | bc -l )
echo $diff hours
# outputs 1.5 hours
sed
reemplaza un :
con una fórmula para convertir a 1/60. Entonces el cálculo del tiempo que se hace por bc
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-19 20:37:11
A partir de la fecha (GNU coreutils) 7.4 ahora puede usar-d para hacer aritmética:
$ date -d -30days
Sat Jun 28 13:36:35 UTC 2014
$ date -d tomorrow
Tue Jul 29 13:40:55 UTC 2014
Las unidades que puedes usar son días, años, meses, horas, minutos y segundos :
$ date -d tomorrow+2days-10minutes
Thu Jul 31 13:33:02 UTC 2014
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-28 13:43:25
Siguiendo la respuesta de Daniel Kamil Kozar, para mostrar horas / minutos / segundos:
echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds"
Así que el script completo sería:
date1=$(date +"%s")
date2=$(date +"%s")
diff=$(($date2-$date1))
echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-03 08:33:23
O envuélvelo un poco
alias timerstart='starttime=$(date +"%s")'
alias timerstop='echo seconds=$(($(date +"%s")-$starttime))'
Entonces esto funciona.
timerstart; sleep 2; timerstop
seconds=2
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-05 18:32:50
% start=$(date +%s)
% echo "Diff: $(date -d @$(($(date +%s)-$start)) +"%M minutes %S seconds")"
Diff: 00 minutes 11 seconds
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-21 15:39:55
Con GNU units
:
$ units
2411 units, 71 prefixes, 33 nonlinear units
You have: (10hr+36min+10s)-(10hr+33min+56s)
You want: s
* 134
/ 0.0074626866
You have: (10hr+36min+10s)-(10hr+33min+56s)
You want: min
* 2.2333333
/ 0.44776119
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-08 21:10:09
date
puede darle la diferencia y formatearlo para usted (se muestran las opciones de OS X)
date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) +%T
# 00:02:14
date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) \
+'%-Hh %-Mm %-Ss'
# 0h 2m 14s
Algún procesamiento de cadenas puede eliminar esos valores vacíos
date -ujf%s $(($(date -jf%T "10:36:10" +%s) - $(date -jf%T "10:33:56" +%s))) \
+'%-Hh %-Mm %-Ss' | sed "s/[[:<:]]0[hms] *//g"
# 2m 14s
Esto no funcionará si colocas primero la hora anterior. Si necesita manejar eso, cambie $(($(date ...) - $(date ...)))
a $(echo $(date ...) - $(date ...) | bc | tr -d -)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-21 12:32:24
Aquí hay una solución usando solo las capacidades de comandos date
usando "ago", y no usando una segunda variable para almacenar el tiempo de finalización:
#!/bin/bash
# save the current time
start_time=$( date +%s.%N )
# tested program
sleep 1
# the current time after the program has finished
# minus the time when we started, in seconds.nanoseconds
elapsed_time=$( date +%s.%N --date="$start_time seconds ago" )
echo elapsed_time: $elapsed_time
Esto da:
$ ./time_elapsed.sh
elapsed_time: 1.002257120
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-24 15:55:48
Me doy cuenta de que este es un post anterior, pero lo encontré hoy mientras trabajaba en un script que tomaría fechas y horas de un archivo de registro y calcularía el delta. El script a continuación es ciertamente excesivo, y recomiendo encarecidamente revisar mi lógica y matemáticas.
#!/bin/bash
dTime=""
tmp=""
#firstEntry="$(head -n 1 "$LOG" | sed 's/.*] \([0-9: -]\+\).*/\1/')"
firstEntry="2013-01-16 01:56:37"
#lastEntry="$(tac "$LOG" | head -n 1 | sed 's/.*] \([0-9: -]\+\).*/\1/')"
lastEntry="2014-09-17 18:24:02"
# I like to make the variables easier to parse
firstEntry="${firstEntry//-/ }"
lastEntry="${lastEntry//-/ }"
firstEntry="${firstEntry//:/ }"
lastEntry="${lastEntry//:/ }"
# remove the following lines in production
echo "$lastEntry"
echo "$firstEntry"
# compute days in last entry
for i in `seq 1 $(echo $lastEntry|awk '{print $2}')`; do {
case "$i" in
1|3|5|7|8|10|12 )
dTime=$(($dTime+31))
;;
4|6|9|11 )
dTime=$(($dTime+30))
;;
2 )
dTime=$(($dTime+28))
;;
esac
} done
# do leap year calculations for all years between first and last entry
for i in `seq $(echo $firstEntry|awk '{print $1}') $(echo $lastEntry|awk '{print $1}')`; do {
if [ $(($i%4)) -eq 0 ] && [ $(($i%100)) -eq 0 ] && [ $(($i%400)) -eq 0 ]; then {
if [ "$i" = "$(echo $firstEntry|awk '{print $1}')" ] && [ $(echo $firstEntry|awk '{print $2}') -lt 2 ]; then {
dTime=$(($dTime+1))
} elif [ $(echo $firstEntry|awk '{print $2}') -eq 2 ] && [ $(echo $firstEntry|awk '{print $3}') -lt 29 ]; then {
dTime=$(($dTime+1))
} fi
} elif [ $(($i%4)) -eq 0 ] && [ $(($i%100)) -ne 0 ]; then {
if [ "$i" = "$(echo $lastEntry|awk '{print $1}')" ] && [ $(echo $lastEntry|awk '{print $2}') -gt 2 ]; then {
dTime=$(($dTime+1))
} elif [ $(echo $lastEntry|awk '{print $2}') -eq 2 ] && [ $(echo $lastEntry|awk '{print $3}') -ne 29 ]; then {
dTime=$(($dTime+1))
} fi
} fi
} done
# substract days in first entry
for i in `seq 1 $(echo $firstEntry|awk '{print $2}')`; do {
case "$i" in
1|3|5|7|8|10|12 )
dTime=$(($dTime-31))
;;
4|6|9|11 )
dTime=$(($dTime-30))
;;
2 )
dTime=$(($dTime-28))
;;
esac
} done
dTime=$(($dTime+$(echo $lastEntry|awk '{print $3}')-$(echo $firstEntry|awk '{print $3}')))
# The above gives number of days for sample. Now we need hours, minutes, and seconds
# As a bit of hackery I just put the stuff in the best order for use in a for loop
dTime="$(($(echo $lastEntry|awk '{print $6}')-$(echo $firstEntry|awk '{print $6}'))) $(($(echo $lastEntry|awk '{print $5}')-$(echo $firstEntry|awk '{print $5}'))) $(($(echo $lastEntry|awk '{print $4}')-$(echo $firstEntry|awk '{print $4}'))) $dTime"
tmp=1
for i in $dTime; do {
if [ $i -lt 0 ]; then {
case "$tmp" in
1 )
tmp="$(($(echo $dTime|awk '{print $1}')+60)) $(($(echo $dTime|awk '{print $2}')-1))"
dTime="$tmp $(echo $dTime|awk '{print $3" "$4}')"
tmp=1
;;
2 )
tmp="$(($(echo $dTime|awk '{print $2}')+60)) $(($(echo $dTime|awk '{print $3}')-1))"
dTime="$(echo $dTime|awk '{print $1}') $tmp $(echo $dTime|awk '{print $4}')"
tmp=2
;;
3 )
tmp="$(($(echo $dTime|awk '{print $3}')+24)) $(($(echo $dTime|awk '{print $4}')-1))"
dTime="$(echo $dTime|awk '{print $1" "$2}') $tmp"
tmp=3
;;
esac
} fi
tmp=$(($tmp+1))
} done
echo "The sample time is $(echo $dTime|awk '{print $4}') days, $(echo $dTime|awk '{print $3}') hours, $(echo $dTime|awk '{print $2}') minutes, and $(echo $dTime|awk '{print $1}') seconds."
Obtendrá la salida de la siguiente manera.
2012 10 16 01 56 37
2014 09 17 18 24 02
The sample time is 700 days, 16 hours, 27 minutes, and 25 seconds.
He modificado un poco el script para hacerlo independiente (es decir. simplemente establezca valores de variables), pero tal vez la idea general también aparezca. Es posible que desee algún error adicional comprobación de valores negativos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-18 16:09:51
Necesitaba un script de diferencia de tiempo para usar con mencoder
(su --endpos
es relativo), y mi solución es llamar a un script Python:
$ ./timediff.py 1:10:15 2:12:44
1:02:29
También se admiten fracciones de segundos:
$ echo "diff is `./timediff.py 10:51.6 12:44` (in hh:mm:ss format)"
diff is 0:01:52.4 (in hh:mm:ss format)
Y puede decirte que la diferencia entre 200 y 120 es 1h 20m:
$ ./timediff.py 120:0 200:0
1:20:0
Y puede convertir cualquier (probablemente fraccional) número de segundos o minutos u horas a hh:mm:ss
$ ./timediff.py 0 3600
1:00:0
$ ./timediff.py 0 3.25:0:0
3:15:0
timediff.py:
#!/usr/bin/python
import sys
def x60(h,m):
return 60*float(h)+float(m)
def seconds(time):
try:
h,m,s = time.split(':')
return x60(x60(h,m),s)
except ValueError:
try:
m,s = time.split(':')
return x60(m,s)
except ValueError:
return float(time)
def difftime(start, end):
d = seconds(end) - seconds(start)
print '%d:%02d:%s' % (d/3600,d/60%60,('%02f' % (d%60)).rstrip('0').rstrip('.'))
if __name__ == "__main__":
difftime(sys.argv[1],sys.argv[2])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-09 15:14:42
Generalizando la solución de @nisetama usando GNU date (trusty Ubuntu 14.04 LTS):
start=`date`
# <processing code>
stop=`date`
duration=`date -ud@$(($(date -ud"$stop" +%s)-$(date -ud"$start" +%s))) +%T`
echo $start
echo $stop
echo $duration
Rendimiento:
Wed Feb 7 12:31:16 CST 2018
Wed Feb 7 12:32:25 CST 2018
00:01:09
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-07 19:02:13
No puedo comentar la respuesta de mcaleaa, de ahí que publique esto aquí. La variable "diff" debe estar en caso pequeño. He aquí un ejemplo.
[root@test ~]# date1=$(date +"%s"); date
Wed Feb 21 23:00:20 MYT 2018
[root@test ~]#
[root@test ~]# date2=$(date +"%s"); date
Wed Feb 21 23:00:33 MYT 2018
[root@test ~]#
[root@test ~]# diff=$(($date2-$date1))
[root@test ~]#
La variable anterior se declaró en minúsculas. Esto es lo que sucedió cuando se usa mayúscula.
[root@test ~]# echo "Duration: $(($DIFF / 3600 )) hours $((($DIFF % 3600) / 60)) minutes $(($DIFF % 60)) seconds"
-bash: / 3600 : syntax error: operand expected (error token is "/ 3600 ")
[root@test ~]#
Entonces, la solución rápida sería así
[root@test ~]# echo "Duration: $(($diff / 3600 )) hours $((($diff % 3600) / 60)) minutes $(($diff % 60)) seconds"
Duration: 0 hours 0 minutes 13 seconds
[root@test ~]#
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-21 15:09:43
Aquí está mi implementación de bash (con bits tomados de otros SO; -)
function countTimeDiff() {
timeA=$1 # 09:59:35
timeB=$2 # 17:32:55
# feeding variables by using read and splitting with IFS
IFS=: read ah am as <<< "$timeA"
IFS=: read bh bm bs <<< "$timeB"
# Convert hours to minutes.
# The 10# is there to avoid errors with leading zeros
# by telling bash that we use base 10
secondsA=$((10#$ah*60*60 + 10#$am*60 + 10#$as))
secondsB=$((10#$bh*60*60 + 10#$bm*60 + 10#$bs))
DIFF_SEC=$((secondsB - secondsA))
echo "The difference is $DIFF_SEC seconds.";
SEC=$(($DIFF_SEC%60))
MIN=$((($DIFF_SEC-$SEC)%3600/60))
HRS=$((($DIFF_SEC-$MIN*60)/3600))
TIME_DIFF="$HRS:$MIN:$SEC";
echo $TIME_DIFF;
}
$ countTimeDiff 2:15:55 2:55:16
The difference is 2361 seconds.
0:39:21
No probado, puede tener errores.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-08 03:42:59