#!/bin/bash # daysago -- given a date in the form month/day/year, calculate how many # days in the past that was, factoring in leap years, etc. # If you are on Linux, this should only be `which date` # If you are on OS X, install coreutils with brew or from source for gdate date="`which date`" function daysInMonth { case $1 in 1|3|5|7|8|10|12 ) dim=31 ;; # most common value 4|6|9|11 ) dim=30 ;; 2 ) dim=29 ;; # depending on if it's a leap year * ) dim=-1 ;; # unknown month esac } function isleap { # returns non-zero value for $leapyear if $1 was a leap year leapyear=$($date -d 12/31/$1 +%j | grep 366) } ####################### #### MAIN BLOCK if [ $# -ne 3 ] ; then echo "Usage: $(basename $0) mon day year" echo " with just numerical values (ex: 7 7 1776)" exit 1 fi $date --version > /dev/null 2>&1 # discard error, if any if [ $? -ne 0 ] ; then echo "Sorry, but $(basename $0) can't run without GNU date." >&2 ; exit 1 fi eval $($date "+thismon=%m;thisday=%d;thisyear=%Y;dayofyear=%j") startmon=$1; startday=$2; startyear=$3 daysInMonth $startmon # sets global var dim if [ $startday -lt 0 -o $startday -gt $dim ] ; then echo "Invalid: Month #$startmon only has $dim days." >&2 ; exit 1 fi if [ $startmon -eq 2 -a $startday -eq 29 ] ; then isleap $startyear if [ -z "$leapyear" ] ; then echo "$startyear wasn't a leapyear, so February only had 28 days." >&2 exit 1 fi fi ################################### ## part two: the number of days since the day you specify. ################################### ### FIRST, DAYS LEFT IN START YEAR # calculate the date string format for the specified starting date startdatefmt="$startmon/$startday/$startyear" calculate="$((10#$($date -d "12/31/$startyear" +%j))) - $((10#$($date -d $startdatefmt +%j)))" daysleftinyear=$(( $calculate )) ### DAYS IN INTERVENING YEARS daysbetweenyears=0 tempyear=$(( $startyear + 1 )) while [ $tempyear -lt $thisyear ] ; do daysbetweenyears=$(($daysbetweenyears + $((10#$($date -d "12/31/$tempyear" +%j))))) tempyear=$(( $tempyear + 1 )) done ### DAYS IN CURRENT YEAR dayofyear=$($date +%j) # that's easy! ### NOW ADD IT ALL UP totaldays=$(( $((10#$daysleftinyear)) + $((10#$daysbetweenyears)) + $((10#$dayofyear)) )) /bin/echo -n "$totaldays days have elapsed between $startmon/$startday/$startyear " echo "and today, day $dayofyear of $thisyear." exit 0