%-------------------------------------------------------------------------------
%       Names: Michael Milvich, Clint Frederickson
%        Date: 2/12/04
% Description: This Prolog program takes in two dates and prints out how many
%              days apart they are. It does this by first figuring out how
%              days the dates are from January 1, 2000 and subtracting the two.
%              Our program can also handle leap years between 2000 and 2010. 
%-------------------------------------------------------------------------------

%-----------------------------------------------------------
% Simple leap year test, only valid between 1901-2099
%-----------------------------------------------------------
leapYear(YEAR) :-
    (YEAR mod 4) =:= 0.

%-----------------------------------------------------------
% Figures out the number of days in a year, 365 for a non
% leap year, 366 for a leap year
%-----------------------------------------------------------
numDaysInYear(YEAR, X) :-
    leapYear(YEAR), X is 366.
numDaysInYear(_, 365).

%-----------------------------------------------------------
% Month facts, defines the number of days in a month, and
% what the previous month is.
%-----------------------------------------------------------
monthInfo(january, none, _, 31).
monthInfo(february, january, YEAR, 29) :- leapYear(YEAR).
monthInfo(february, january, _, 28).
monthInfo(march, february, _, 31).
monthInfo(april, march, _, 30).
monthInfo(may, april, _, 31).
monthInfo(june, may, _, 30).
monthInfo(july, june, _, 31).
monthInfo(august, july, _, 31).
monthInfo(september, august, _, 30).
monthInfo(october, september, _, 31).
monthInfo(november, october, _, 30).
monthInfo(december, november, _, 31).

%-----------------------------------------------------------
% This figures out how many days to the start of a year
%-----------------------------------------------------------
daysToStartOfYear(2000, 0).
daysToStartOfYear(YEAR, X) :-
    LAST_YEAR is YEAR - 1,
    daysToStartOfYear(LAST_YEAR, Z),
    numDaysInYear(LAST_YEAR, Y),
    X is Y + Z.
    
%-----------------------------------------------------------
% Figures out how many days since 1/1/2000 to the date
%-----------------------------------------------------------
daysToDate(date(january, DAY, YEAR), X) :-
    daysToStartOfYear(YEAR, DAYS),
    X is DAY + DAYS - 1.
daysToDate(date(MONTH, DAY, YEAR), X) :-
    monthInfo(MONTH, PMONTH, YEAR, _),
    daysToDate(date(PMONTH, 0, YEAR), D1),
    monthInfo(PMONTH, _, YEAR, D2),
    X is DAY + D1 + D2.
    
%-----------------------------------------------------------
% This will print out "day" if DAYS is one, else "days"
%-----------------------------------------------------------
writeDays(DAYS) :-
    DAYS =:= 1, write(' day').
writeDays(_) :-
    write(' days').
    
%-----------------------------------------------------------
% This takes two dates and prints out how many days appart
% they are.
%-----------------------------------------------------------
distance(DATE1, DATE2) :-
    daysToDate(DATE1, X),
    daysToDate(DATE2, Y),
    DAYS is abs(Y - X),
    write(DAYS), writeDays(DAYS).