¿Cómo encontrar la diferencia entre dos marcas de tiempo hasta milisegundos?

10

Soy nuevo en los scripts de shell. El corazón de mi script es encontrar la diferencia entre dos marcas de tiempo hasta milisegundos. Conmigo tengo un archivo con contenido de marcas de tiempo solo como

2012-09-13 15:00:29,290 2012-09-13 15:00:29,297
2012-09-13 15:00:29,428 2012-09-13 15:00:29,447

De esta manera, tengo alrededor de 30k registros, donde no debería enfrentar ningún problema de rendimiento cuando ejecuto el script. Muchos factores, como el año bisiesto, los meses con 31 días, etc., aparecen cuando intento escribir un guión para esto.

¿Alguien puede ayudarme en esto por favor?

Vamshi G
fuente
1
¿DST entra en escena? Segundos bisiestos? ¿Cuáles son las reglas del horario de verano? ¿Han cambiado con el tiempo en tu país? ¿Tiene que lidiar con fechas anteriores a 1970, o antes de cambiar al calendario gregoriano?
Stéphane Chazelas

Respuestas:

13

No es necesario realizar un análisis complejo, la hará toda la magia por ti, con la ayuda de su amigo, :

#!/bin/bash
while read d1_1 d1_2 d2_1 d2_2; do
  secdiff=$((
    $(date -d "$d2_1 $d2_2" +%s) - $(date -d "$d1_1 $d1_2" +%s)
  ))
  nanosecdiff=$((
    $(date -d "$d2_1 $d2_2" +%N) - $(date -d "$d1_1 $d1_2" +%N)
  ))
  printf "%s %s - %s %s = %d milliseconds\n" $d2_1 $d2_2 $d1_1 $d1_2 $((
    (secdiff * 1000) + (nanosecdiff / 1000000)
  ))
done < YOUR_FILE.txt

SALIDA

2012-09-13 15:00:29,297 - 2012-09-13 15:00:29,290 = 7 milliseconds
2012-09-13 15:00:29,447 - 2012-09-13 15:00:29,428 = 19 milliseconds

Ver man date

NOTA

  • date -d es muy útil, convierte marcas de tiempo
  • %ses el tiempo de la época (segundos desde 01-01-1970)
  • %Nson nanosegundos
  • $(( ))y (( ))es para basharitmética, ver http://mywiki.wooledge.org/ArithmeticExpression
  • $( ) representa command substitution

¿Esto también se ajusta a tus necesidades?

Gilles Quenot
fuente
1
Se corrigió un error aritmético (concatenación de segundos y nanosegundos). Ahora calculo primero los segundos (OP no preguntó eso, pero para completar y robustez en la reutilización)
Gilles Quenot
0

Un lenguaje de script como Perl, Python o Ruby será rápido y requerirá poco esfuerzo. Por ejemplo, con Perl y Date :: Parse :

perl -MDate::Parse -l -ne 's/,/./g; split; print str2time("$_[2] $_[3]") - str2time("$_[0] $_[1]")'

(Para cada línea, sustituir ,por ., dividir la línea en palabras $_[0]a través $_[3], analizar las fechas formadas por los dos primeros y dos palabras siguientes, e imprimir la diferencia).

Gilles 'SO- deja de ser malvado'
fuente
El "pequeño esfuerzo" es bastante relativo. Claro, si eres un programador X y conoces la biblioteca Y, es muy fácil. Así es como siempre es. En realidad, me sorprende que un programador de Python no haya saltado aquí todavía. Supongo que es solo cuestión de tiempo ...: - \
Mike S
0

Acabo de encontrar esta publicación, hay, al menos hoy, una datesolución más simple . Usando el marco en la respuesta de @Gilles Quenot (habría escrito un comentario a su respuesta, pero no suficiente reputación):

while read d1_1 d1_2 d2_1 d2_2
do
    date -d "$d2_1 $d2_2 $(date -d "$d1_1 $d1_2" +%s.%N) seconds ago" +%s.%N
done << END
2012-09-13 15:00:29,290 2012-09-13 15:00:29,297
END

El resultado:

$ ./time_elapsed.sh 
0.007000000

Usar en %3Nlugar de %Ntruncará la salida a milisegundos.

Zoltan K.
fuente