Swap d1 and d2 if you want the date calculation the other way, or get a bit fancier to make it not matter. Furthermore, in case there is a non-DST to DST transition in the interval, one of the days will be only 23 hours long; you can compensate by adding ½ day to the sum.

This came up when using date -d "$death_date - $y years - $m months - $d days" to get a birth date (for genealogy). That command is WRONG. Months aren't all the same length, so (date + offset) - offset != date. Ages, in year/month/day, are measures going forwards from the date of birth.

Date gives the correct output in both cases, but in the second case you were asking the wrong question. It matters WHICH 11 months of the year the +/- 11 cover, before adding/subtracting days. For example:

For subtracting to be the inverse operation of adding, the order of operations would have to be reversed. Adding adds years, THEN months, THEN days. If subtracting used the opposite order, then you'd get back to your starting point. It doesn't, so you don't, if the days offset crosses a month boundary in a different length month.

If you need to work backwards from an end date and age, you could do it with multiple invocations of date. First subtract the days, then the months, then the years. (I don't think it's safe to combine the years and months in a single date invocation, because of leap years altering the length of February.)

Line 2 assigns the value from the out of date to the variable
DATEfirstnum. The -d flag displays the string in a time format in
this case May 14th 2014 and +"%j" tells date to format the output
to just the day of the year (1-365).

Line 3 is the same as Line 2 but with a different date and
different format for the string, December 31st, 2014.

Line 4 assigns the value DAYSdif to the difference of the two
days.

Line 5 displays the value of DAYSdif.

This works with the GNU version of date, but not on the PC-BSD/FreeBSD version. I installed coreutils from ports tree and used the command /usr/local/bin/gdate instead.

This script will not run. There is a typo on the last line and spaces around the variable assignments, so bash is attempting to run a program called DATEfirst name with two arguments. Try this: DATEfirstnum=$(date -d "$1" +%s)DATElastnum=$(date -d "$2" +%s) Also, this script will not be able to calculate the difference between two different years. +%j refers to day of year (001..366) so ./date_difference.sh 12/31/2001 12/30/2014 outputs -1. As other answers have noted you need to convert both dates into seconds since 1970-01-01 00:00:00 UTC.
–
SixFeb 28 at 13:29

I usually prefer having the time/date in unix utime format (number of seconds since the epoch, when the seventies begun, UTC). That way it always boils down to plain subtraction or addition of seconds.

The problem the usually becomes transforming a date/time into this format.

If you have GNU date, you can get it with date '+%s'
At the time of writing, the current time is 1321358027.