Beware! Many of the bash solutions here are broken for date ranges that span the start of daylight saving time (where applicable). This is because the $ ((math)) construct performs the "floor" / truncation operation on the resulting value, returning only an integer. Let me illustrate:
DST began March 8 this year in the US, so letβs use a date range that covers this:
start_ts=$(date -d "2015-03-05" '+%s') end_ts=$(date -d "2015-03-11" '+%s')
Let's see what happened with double parentheses:
echo $(( ( end_ts - start_ts )/(60*60*24) ))
Returns "5".
Doing this with "bc" gives us a different result with greater accuracy:
echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc
Returns "5.95" - the missing 0.05 is a lost hour after switching DST.
So how to do it right?
I would suggest using this instead:
printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc)
Here "printf" rounds off the more accurate result calculated by "bc", giving us the correct date range of "6".
Edit: highlighting the answer in a comment from @ hank-schultz below, which I used recently:
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s) )/(60*60*24) ))
This should also be a safe second step, provided that you always subtract the earlier date from the later, since the seconds of the jump will only add to the difference - truncation is effectively rounded to the correct result.
evan_b Mar 12 '15 at 19:53 2015-03-12 19:53
source share