My solution is short, and I have previously written versions in C, Lua, Python, Perl, Awk, Ksh, and Csh (the version below is ksh.) Some specific questions you can answer with ansi_dn, nd_isna, and dow: Given a date YYYY MM DD, what is the date 100 days before or after? Given a date, what is the day of the week? Given two dates, how many days are in between?
#==========================================================================
# Calendar operations: Valid for dates in [1601-01-01, 3112-12-30].
# Adapted from a paper by B.E. Rodden, Mathematics Magazine, January, 1985.
#==========================================================================
# ANSI day number, given y=$1, m=$2, d=$3, starting from day number 1 ==
# (1601,1,1). This is similar to COBOL's INTEGER-OF-DATE function.
function ansi_dn {
integer y=$1 ys=$(($1-1601)) m=$2 d=$3 s dn1 isleap h
((isleap = y%4==0 && (y%100!=0 || y%400==0) ))
((dn1 = 365*ys + ys/4 - ys/100 + ys/400)) # first day number of given year.
((s = (214*(m-1) + 3)/7 + d - 1)) # standardized day number within year.
((h = -2*(!isleap && s>58) - (isleap && s>59) )) # correction to actual dn.
print -- $((1 + dn1 + s + h))
}
# Inverse of ansi_dn, for adn=$1 in [1, 552245], with returned dates in
# [1601-01-01, 3112-12-30]. Similar to COBOL's DATE-OF-INTEGER function.
function nd_isna {
integer y a s ys d0=$(($1-1)) dn1 isleap h
typeset -Z2 m d
((ys = d0/365))
((365*ys + ys/4 - ys/100 + ys/400 >= $1)) && ((ys -= 1))
((dn1 = 365*ys + ys/4 - ys/100 + ys/400))
((y = 1601 + ys))
((a = d0 - dn1))
((isleap = y%4==0 && (y%100!=0 || y%400==0) ))
((h = -2*(!isleap && a>58) - (isleap && a>59) ))
((s = a - h))
((m = (7*s + 3)/214 + 1))
((d = s - (214*(m-1) + 3)/7 + 1))
print -- $y $m $d
}
# Day of the week, given $1=ansi_dn. 0==Sunday, 6==Saturday.
function dow { print -- $(($1%7)); }