11

I am new to shell scripting. The heart of my script is to find the difference between two timestamps up to milliseconds. With me I have a file with content of timestamps only as

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

Like this I have around 30k records, where I should not face any performance issue when I execute script. Many factors like leap year, months with 31 days etc come into picture when I am trying to write script for this.

Can anyone help me on this please?

1
  • 1
    Does DST come into the picture? Leap seconds? What are the DST rules? Have they changed over time in your country? Do you have to deal with dates before 1970, or before a switch to the gregorian calendar? – Stéphane Chazelas Nov 20 '12 at 10:07
14

No need to do complex parsing, will do all the magic for you, with the help of his friend, :

#!/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

OUTPUT

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

See man date

NOTE

  • date -d is very useful, it convert timestamps
  • %s is the epoch time (seconds since 01-01-1970)
  • %N is nanoseconds
  • $(( )) and (( )) is for bash arithmetic, see http://mywiki.wooledge.org/ArithmeticExpression
  • $( ) stands for command substitution

Is this fit your needs as well ?

1
  • 1
    Corrected an arithhmetic error (concatenating seconds and nanoseconds). Now I first compute the seconds (OP don't asked that, but for completeness and robustness in re-use) – Gilles Quenot Nov 20 '12 at 8:17
1

I just came across this post, there is - at least today - a simpler date-based solution. Using the framework in the answer of @Gilles Quenot (would have written a comment to his anwser, but not enough reputation):

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

The result:

$ ./time_elapsed.sh 
0.007000000

Using %3N instead of %N will truncate the output to milliseconds.

0

A scripting language such as Perl, Python or Ruby will be fast and require little effort. For example, with Perl and Date::Parse:

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

(For each line, replace , by ., split the line into words $_[0] through $_[3], parse the dates formed by the first two and next two words, and print the difference.)

2
  • "Little effort" is quite relative. Sure, if you're a X programmer and know about the Y library, it's a cinch. That's how it always is. Actually, I'm surprised a Python programmer hasn't jumped in here yet. I figure it's just a matter of time... :-\ – Mike S Dec 6 '15 at 6:58
  • That's why people give a full solution here. That way you don't have to be an X programmer or know about the Y library. And you still benefit from the "little effort" of having one line in your script and not 10. – CherryDT Apr 14 '20 at 8:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.