phone: (540)338-0194
email: ken@kenhamady.com

 ReCrystalize

How to find Good Friday (or Easter) for any year:

This is Mikes original formula with full historical comments and a detailed description of what each step is doing.   It will work just as it is, or you can use the short version.  Both should give the exact same result.

// FUNCTION: @GoodFridayHoliday
// LANGUAGE: Crystal Reports 8.5 / Crystal syntax
// REQUIRES: Functions; @yr
// RETURNS: dateVar: date of good friday
// DESCRIPTION:
// Calculates the date of Good Friday (Friday before Easter)
// CHANGE LOG:
// Written 6/28/03 by Mike Cook

numberVar yr := {@yr}; // The year for which to determine the date of Good Friday.

    // The following calculation of the Date for Easter is based on Oudin's algorithm for
    // determining the date of Easter and follows the algorithm given in the New Scientist
    // magazine, issue No. 228 (Vol. 9) page 828 (March 1961). It was originally coded in 
    // Multics PL/1 by Dennis Capps in 9/80 to fix bug a in the easter calculation in a
    // program called calendar originally written by Tom Van Vleck of MIT in 1972.  It was
    // converted to Crystal and modified to return the date of Good Friday by Mike Cook in
    // 2003.  The comments are mostly from the original PL/1.It should be valid for any date
    // from 1583 to 4099, so we may have a year 4K issue.

    Local numberVar a := yr Mod 19;      // Find position of year in 19-year Lunar Cycle,
                                        // called the Golden Number.
    Local numberVar b := yr \ 100;      // b is century number
    Local numberVar c := yr Mod 100;     // c is year number within century
    Local numberVar d := b \ 4;
    Local numberVar e := b Mod 4;       // d, e and i, k are used in leap year adjustments.
    Local numberVar i := c \ 4;
    Local numberVar k := c Mod 4;

    // The next step computes a correction factor used in the following step
    // which computes the number of days between the spring equinox
    // and the first full moon thereafter.  The correction factor is needed
    // to keep the approximation in line with the observed behavior of the moon.
    // It moves the full moon date back by one day eight times in every 2500 years,
    // in century years three apart, with four years at the end of the cycle.
    // The constant 13 corrects the correction for the fact that this
    // cycle was decreed to start in the year 1800.
 
    Local numberVar g := (8 * b + 13) \ 25;

    // Now the number of days after the equinox (21 March, by definition) that
    // we find the next full moon.  This is a number between 0 and 29.
    // The term 19*a advances the full moon 19 days for each year of the
    // Lunar Cycle, for a total of 361 days in the 19 years.  The other 4.24 days
    // are made up when a returns to zero on the next cycle.  Thus, the
    // full moon dates repeat every 19 years.  The term b-d advances the
    // date by one day for three out of every four century years, the
    // years which are not leap years although divisible by 4.
    // The term g is the correction factor calculated above, and 15
    // adjusts this whole calculation to the actual conditions at that
    // date on which the scheme began, probably in Oct of 1582.
 
    Local numberVar h := ((19 * a) + b - d - g + 15) Mod 30;

    // Now we are interested in how many days we have to wait after the
    // full moon until we get a Sunday (which has to be definitely after
    // the full moon).  The following step calculates a number l which is
    // one less than the number of days.  Every ordinary year ends on the
    // same day of the week on which it started;  a leap year ends on the
    // day of the week following the one on which it started.  Thus, if
    // it is known on what day of the week a date occurred in any year
    // it is possible to calculate its day of the week in another year
    // by marching through the week one day for each regular year and
    // two for each leap year.
    //      The term k is the number of ordinary years
    // since the last leap year;  each such year brings the date of the
    // full moon one day closer to Sunday, and so reduces the number of
    // days to be waited (unless it goes negative, but modular arithmetic
    // theory makes -1 := 6 where the modulus is 7).
    //      The term i is the number of leap years so far in the current century.
    // each leap year has with it three ordinary years, and each such group
    // advances the day of the week by 5 days.  But in modulo 7 arithmetic
    // subtracting 5 days is equivalent to adding 2 days.  So we add
    // two days for each group of four years in the current century.
    //      Since a century consists of 25 groups of four years, it advances
    // the day of the week by 124 or 125 days depending on whether the
    // century year is an ordinary or leap year.  The remainders when
    // these numbers are divided by seven are 5 and 6 respectively.
    // The term e is the number of ordinary century years since the
    // last leap century year.  As with the groups of four years, we
    // add two days for each rather than subtract 5 for each.
    //      Every fourth century year is a leap year;  therefore,
    // each group of four centuries advances the day of the week by
    // 3*5+6 := 21 days, or 0 in modulo 7 arithmetic, and no
    // term is necessary for time before the last leap century year.
    // The constant term 32 adjusts the calculation for the day of the
    // week of the equinox when the scheme was put into effect.  It also
    // is larger than necessary by 28 in order to assure that the
    // subtractions of k and h never reduce the dividend below 0.
    //      Thus, mod(2*e + 2*i - k + 32, 7) gives one less than the number
    // of days between the equinox and its following Sunday.  But we need to
    // calculate the number of days after the full moon.  The term h,
    // calculated in the previous step, gives the number of days after
    // the equinox that the full moon occurs.  Each of those days brings
    // the full moon closer to the actual Sunday of Easter,
    // so it reduces the number of days after the full moon until Easter.
    // (Again, if h > 6, modular arithmetic theory readjusts the result to
    // another cycle of 0 to 6, and here the constant 32 keeps the dividend > 0.)
  
    Local numberVar l := ((2 * e) + (2 * i) - k + 32 - h) Mod 7;
 
    // The calendar set up by Pope Gregory XIII and his advisor, the astronomer
    // Clavius, provided for official full moon dates as well as matching
    // the equinoxes and solstices with their nominal dates.  But, since
    // the period of the moon is not an exact number of days, some fudging
    // was needed here as elsewhere in the calendar system.  Some of the
    // periods between successive full moons in the Lunar Cycle are 30 days,
    // some 29 days.  Clavius then arranged the periods carefully so
    // that if a full moon fell on 20 March (the day before the equinox),
    // the period following it would be of 29 days.  The effect of this
    // arrangement is that Easter can never occur later than 25 April.
    // The above calculations assume uniform 30-day lunar periods.  In rare
    // cases (e.g., 1954 and 1981) one of these 29-day lunar periods causes
    // the full moon to fall on a Saturday where a 30-day period would put
    // it on a Sunday.  The following step calculates the fudge factor for
    // this situation.  The result m is 0 if no fudging is necessary, or
    // 1 if fudging is required.
    
    Local numberVar m := (a + (11*h) + (19*l)) \ 433;

    // Now we have calculated the number of days which will elapse between
    // 21 march and Easter: h + (l + 1) - 7*m.  The last two steps
    // turn this into a month and day.  In the first expression, the constant
    // 90 assures that the the quotient will be at least 3 (= March).
    // If the elapsed days exceed 9, then the quotient will be 4 (= April).
    // In the second expression, if month := 3 then 33*month + 19 := 118 and the
    // remainder of that part of the expression is 22;  when month := 3,
    // l + h - 7*m < 10, so 22 < day <= 31.
    // If month := 4, 33*month := 132, and since h + l - 7*m > 9, the whole
    // expression satisfies 5*32 := 160 < expr.  The remainder is greater
    // than 0 and less than 26.

    // The following converts the number of days to Easter to the number of days
    // to Good Friday: h + (l + 1) - 7*m -2. (2 days before Easter)

    Local numberVar days_to_good_friday := h + l - (7*m) - 2; 
  
    Local numberVar mo := (days_to_good_friday + 90) \ 25;
    Local numberVar da := (days_to_good_friday + (33 * mo) + 19) Mod 32;

cdate ( yr, mo, da) // Returns the date of Good Friday