The bash way - convert the dates into %y%m%d format and then you can do this straight from the command line:
echo $(( ($(date --date="031122" +%s) - $(date --date="021020" +%s) )/(60*60*24) ))
If you have GNU date
, it allows to print the representation of an arbitrary date (-d
option).
In this case convert the dates to seconds since EPOCH, subtract and divide by 24*3600.
Example using GNU date (from https://stackoverflow.com/a/9008871/215713):
let DIFF=($(date +%s -d 20210131)-$(date +%s -d 20210101))/86400
echo $DIFF
30
This also works with dates in other formats, for example "2021-01-31".
Other answers suggest ways to do it that don't require GNU date.
tl;dr
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s)) / (60*60*24) ))
Watch out! Many of the bash solutions here are broken for date ranges which span the date when daylight savings time begins (where applicable). This is because the $(( math )) construct does a 'floor'/truncation operation on the resulting value, returning only the whole number. Let me illustrate:
DST started March 8th this year in the US, so let's use a date range spanning that:
start_ts=$(date -d "2015-03-05" '+%s')
end_ts=$(date -d "2015-03-11" '+%s')
Let's see what we get with the double parentheses:
echo $(( ( end_ts - start_ts )/(60*60*24) ))
Returns '5'.
Doing this using 'bc' with more accuracy gives us a different result:
echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc
Returns '5.95' - the missing 0.05 being the lost hour from the DST switchover.
So how should this be done correctly?
I would suggest using this instead:
printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc)
Here, the 'printf' rounds 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 have been using lately:
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s) )/(60*60*24) ))
This should also be leap second safe as long as you always subtract the earlier date from the later one, since leap seconds will only ever add to the difference - truncation effectively rounds down to the correct result.
And in python
$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398
This works for me:
A="2002-10-20"
B="2003-11-22"
echo $(( ($(date -d $B +%s) - $(date -d $A +%s)) / 86400 )) days
Prints
398 days
What is happening?
date -d
to handle time stringsdate %s
to convert time strings to seconds since 1970 (unix epoche)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With