0

I have two dates as follows:

2019-01-06 00:02:10 | END
2019-01-05 23:52:00 | START

How could I calculate and print the difference between START and END dates in seconds?

For above case I would like to get something like:

610
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
nightfury
  • 384
  • 6
  • 18
  • 4
    Welcome to SO. Stack Overflow is a question and answer site for professional and enthusiast programmers. The goal is that you add some code of your own to your question to show at least the research effort you made to solve this yourself. – Cyrus Jan 09 '19 at 04:57
  • will make sure about it next time. – nightfury Jan 09 '19 at 06:20
  • You could also fix this one, it's not too late! Click the [edit](https://stackoverflow.com/posts/54103307/edit) link under the question to get started. :) – ghoti Jan 09 '19 at 13:52

5 Answers5

2

With bash and GNU date:

while read d t x x; do
  [[ $x == "END" ]] && end="$d $t" 
  [[ $x == "START" ]] && start="$d $t"
done < file

end=$(date -u -d "$end" '+%s')
start=$(date -u -d "$start" '+%s')

diff=$(($end-$start))
echo "$diff"

Output:

610

See: man date

Cyrus
  • 84,225
  • 14
  • 89
  • 153
2

Assuming GNU implementation based OS, you can use date's option %s and -d to calculate the time difference in seconds using command substitution and arithmetic operations.

START="2019-01-05 23:52:00"
END="2019-01-06 00:02:10"

Time_diff_in_secs=$(($(date -d "$END" +%s) - $(date -d "$START" +%s)))
echo $Time_diff_in_secs

Output:

610

Hope this helps!!!

User123
  • 1,498
  • 2
  • 12
  • 26
  • That's not part of bash, and it's not portable. Do you know what operating system the OP is running? – ghoti Jan 09 '19 at 05:45
  • 2
    I didn't vote down. It makes sense to wait until the questioner has shown what he has already tried. – Cyrus Jan 09 '19 at 05:47
  • 4
    @ghoti: Sir, I can see the `bash` tag in the question, so was able to answer accordingly. Also, i didn't expected a Downvote for the answer. – User123 Jan 09 '19 at 05:51
  • 3
    Bash runs on more than Linux, and the `date` command is not part of bash. Bash is the default shell on macOS. If I attempt your solution on macOS, I get an error, because `date -d` *means something else* in different operating systems. If your answer is OS-specific and the question is not, you should note in your answer that it is only applicable in certain environments. Ideally, your answer should be *portable* so that it will work in any environment. That makes it valuable to whoever finds the question in the future, regardless of what OS they run. – ghoti Jan 09 '19 at 06:03
  • I do understand that I did not add my way of fixing it -- but certainly I was clueless because I had other things to figure -- how to get to these date's itself as I am using mysql and getting a response into a text and then finding the difference between START and END record. @User123 - Thank you. I will make sure to add my fix from next time. – nightfury Jan 09 '19 at 06:30
  • Ah, so this was an [XY Problem](https://mywiki.wooledge.org/XyProblem). You could do this with much better performance right in MySQL. See [this](https://stackoverflow.com/a/3528228/1072112) answer. – ghoti Jan 09 '19 at 13:55
1

What you're asking for is difficult verging on impossible using pure bash. Bash doesn't have any date functions of its own. For date processing, most recommendations you'll get will be to use your operating system's date command, but the usage of this command varies by operating system.

In BSD (including macOS):

start="2019-01-05 23:52:00"; end="2019-01-06 00:02:10"
printf '%d\n' $(( $(date -j -f '%F %T' "$end" '+%s') - $(date -j -f '%F %T' "$start" '+%s') ))

In Linux, or anything using GNU date (possibly also Cygwin):

printf '%d\n' $(( $(date -d "$end" '+%s') - $(date -d "$start" '+%s') ))

And just for the fun of it, if you can't (or would prefer not to) use date for some reason, you might be able to get away with gawk:

gawk 'END{ print mktime(gensub(/[^0-9]/," ","g",end)) - mktime(gensub(/[^0-9]/," ","g",start)) }' start="$start" end="$end" /dev/null

The mktime() option parses a date string in almost exactly the format you're providing, making the math easy.

ghoti
  • 45,319
  • 8
  • 65
  • 104
1
START="2019-01-05 23:52:00"
END="2019-01-06 00:02:10"
parse () {
    local data=(`grep -oP '\d+' <<< "$1"`)
    local y=$((${data[0]}*12*30*24*60*60))
    local m=$((${data[1]}*30*24*60*60))
    local d=$((${data[2]}*24*60*60))
    local h=$((${data[3]}*60*60))
    local mm=$((${data[4]}*60))
    echo $((y+m+d+h+mm+${data[5]}))
}
START=$(parse "$START")
END=$(parse "$END")
echo $((END-START)) // OUTPUT: 610
Darby_Crash
  • 446
  • 3
  • 6
1

Was trying to solve the same problem on a non-GNU OS, i.e. macOS. I couldn't apply any of the solutions above, although it inspired me to come up with the following solution. I am using some in-line Ruby from within my shell script, which should work out of the box on macOS.

START="2019-01-05 23:52:00"
END="2019-01-06 00:02:10"

SECONDS=$(ruby << RUBY
require 'date'
puts ((DateTime.parse('${END}') - DateTime.parse('${START}')) * 60 * 60 * 24).to_i
RUBY)

echo ${SECONDS}
# 610
dpzz
  • 121
  • 3