/* int DaysBetweenDates365(m1,d1,y1, m2,d2,y2) * * ARGUMENT * int m1,d1,y1; - Base Date * int m2,d2,y2; - Date to compare with base * * DESCRIPTION * Compares two dates in date args format, forming the difference in * whole days. The result is a signed number: * * 0 if dates are same, * +n if date1 > date2 * -n if date1 < date2 * * SIDE EFFECTS * None. * * RETURNS * +,-, or 0 days. 0 can indicate an error. * * POSSIBLE ERROR CODES * GM_ARGVAL * GM_OVERFLOW * * AUTHOR * 05-Aug-1987 12:43:39 * Copyright (C) 1987-1990 Greenleaf Software Inc. All rights reserved. * * MODIFICATIONS * * 01-Jan-1989 Corrected for true Gregorian Calendar * * DISCUSSION * * It may not be entirely clear when reading this code just what is going * on. First of all, the calendar used is the Greenleaf version of the * Gregorian calendar. We assume in this calendar that Gregorian time * extends backwards to the year 0, and forward forever, more or less. * A leap year occurs every four years. Except when the year is evenly * divisible by 100, like the year 1900, when there is no leap year. Except * when the year is evenly divisible by 400, in which case there really * is a leap year. * * The way this algorithm works is relatively simple. There are four * mysterious variables in this program: n1, n2, x and z. n1 and n2 are * relatively easy to understand. These variables are simple the number * of days since January 1, year 0. The difference between these two numbers * is the actual number returned by this function. * * In order to calculate the number of days since 1/1/0, we can start by * adding 365 days per year: * * n = 365 * y * * This gets a pretty good rough number, but it doesn't take into account * the leap years. Given the Greenleaf Gregorian calendar, we can add in * all the days accounted for by leap years like this: * * n = 365 * y + y/4 - y/100 + y/400 * * This works pretty well, but it leaves us with one problem: we are * adding in a leap day in leap years, even if the month is January * or February. On January 1, 1984, we haven't hit the leap day yet, so * we shouldn't add it in. This is where z comes from. y is the actual * year, but z is the year used for calculation of leap days: * * if ( m <= 2 ) * z = y - 1; * else * z = y; * n = 365 * y + y/4 - y/100 + y/400 * * At this point, n is accurate for January 1 of the given year. Now we * have to add in the days accounted for by the months in the selected year. * A good guess on how to do this is to just add 31 days per month: * * n = 365 * y + y/4 - y/100 + y/400 + 31*(m - 1) * * The only problem is that starting with month 3, there will be errors * in the calculation. The good news is that a simple formula will generate * a correction factor, which is x. The formula for x is (4*m + 23) / 10. * This just happens to generate the correct sequence of numbers. A different * way would be to create an x array {0, 0, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7}; * So now my formula looks like this: * * if ( m <= 2 ) { * x = 0; * z = y - 1; * } else { * z = y; * x = ( 4 * m + 23 ) / 10 ; * } * n = 365 * y + y/4 - y/100 + y/400 + 31*(m - 1) * * The final step is to add in the day of the month, to account for all the * days in the current month. Do that and you are done. * */ #include #include "gmsystem.h" int DaysBetweenDates365(m1,d1,y1,m2,d2,y2) int m1,d1,y1,m2,d2,y2; { long n1, n2, n; int x, z; _MacStart(GM_DBD365); if (m1<1||m1>12||d1<1||d1>31||y1<0||y1>9999|| m2<1||m2>12||d2<1||d2>31||y2<0||y2>9999) { _MacErr(GM_ARGVAL); _MacRet(GM_ARGVAL); } if (m1<=2) { x=0; z=y1-1; } else { x=(4*m1 + 23) / 10; z=y1; } n1 = (long) y1 * 365L + (long) (31*(m1-1) + d1 + z/4 - z/100 + z/400 - x); if (m2<=2) { x=0; z=y2-1; } else { x=(4*m2 + 23) / 10; z=y2; } n2 = (long) y2 * 365L + (long) (31*(m2-1) + d2 + z/4 - z/100 + z/400 - x); n = n1 - n2; if (n<-32768L||n>32767L) { _MacErr(GM_OVERFLOW); _MacRet(GM_OVERFLOW); } _MacRet((int) n); }