/* hard/time/easter.c librock_CHISEL _summary Calculate the serial day number of Easter Sunday Copyright (c) 2001-2002, Forrest J. Cavalier III, doing business as Mib Software, Saylorsburg Pennsylvania USA Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef librock_NOTLIBROCK /**************************************************************/ /* ABOUT THIS FILE: GUIDE TO QUICK REUSE WITHOUT REWORK This file uses many preprocessor conditional blocks and features to publish http://www.mibsoftware.com/librock/ You can disable those features with little or no editing, and reuse this file: 1. At compile time, enable this conditional block by defining the preprocessor symbol librock_NOTLIBROCK, either with a compiler command line parameter, or as a #define in a source file which then #includes this source file. 2. Define any preprocessor symbols in this block (if any) appropriately for your machine and compilation environment. 3. Copy and use the declarations from this block in your source files as appropriate. This file is originally from the librock library, which is Free (libre), free (no cost), rock-stable API, and works on gcc/MSVC/Windows/Linux/BSD/more. Get originals, updates, license certificates, more, at http://www.mibsoftware.com/librock/ (Change log appears at end of this file.) */ #define librock_ISOLATED #define librock_PRIVATE #define librock_PTR #define librock_CONST const /**************************************************************/ #endif #ifndef librock_ISOLATED /**************************************************************/ #define librock_IMPLEMENT_easter #include #include /**************************************************************/ #endif #ifdef librock_IMPL_LIDESC #ifndef librock_NOIMPL_LIDESC_easter /* License description features are documented at http://www.mibsoftware.com/librock/ */ /**************************************************************/ #include /* librock_LIDESC_HC=12440211096131f5976d36be0cddca4cd9152e45 */ void *librock_LIDESC_easter[] = { "\n" __FILE__ librock_LIDESC_librock "\n", 0 }; /**************************************************************/ #endif #endif #ifndef librock_WRAP /* Function wrapping and tracing features are documented at http://www.mibsoftware.com/librock/ */ /**************************************************************/ #define librock_body_EasterSdn librock_EasterSdn /**************************************************************/ #endif #ifndef librock_NOIMPL_PaschalFullMoonTable #define April (31-1) /* So that April+1 = 31 */ #define March 0 librock_PRIVATE int PaschalFullMoonTable[19] = { April+5, March+25, April+13, April+2, March+22, April+10, March+30, April+18, April+7, March+27, April+15, April+4, March+24, April+12, April+1, March+21, April+9, March+29, April+17}; #endif #ifndef librock_NOIMPL_easter /**************************************************************/ long librock_body_EasterSdn(int year,int julian) {/* Copyright 1998-2001, Forrest J. Cavalier III d-b-a Mib Software Licensed under BSD-ish license, NO WARRANTY. Copies must retain this block. License, originals, details: http://www.mibsoftware.com/librock/ */ #ifdef librock_MANUAL_easter /* librock_easter - Calculate the serial day number of Easter Sunday */ /**/ #include long librock_EasterSdn( int year, int julian); /* This function calculates the serial day number (SDN) of Easter, using either the Julian calendar calculation (valid from 326 to 4099 A.D.) or the Gregorian calendar calculation (valid from 1583 to 4099 A.D.) (Non-zero for the parameter @julian will use the Julian Calendar.) Even though the Gregorian calendar has the most widespread use, some Orthodox churches continue to use the Julian calendar to calculate the date of Easter. (This date, Orthodox Easter, can be expressed as a Gregorian date, even though it is calculated with the Julian calendar.) If the year is out of range, 0 is returned. The first Easter after the Gregorian calendar was created was in 1583. Easter was calculated differently before 326 A.D. Sometime after 4099 there will need to be a correction to remove an extra leap year. The serial day number returned by this function is compatible to Scott E. Lee's sdncal routines. This was authored by Forrest J. Cavalier III based on information and algorithms printed at http://www.assa.org.au/edm.html#OrthCalculator, and from http://www.oremus.org/liturgy/etc/ktf/app/easter.html This was tested to match all years 1700-2299 listed at http://www.assa.org.au/edm.html (Other tests indicate it is also accurate for years outside that range.) Typical use is */ #ifdef librock_TYPICAL_USE_EasterSdn #include int year = 2000; int month; int day; librock_SdnToGregorian(librock_EasterSdn(year,0),&year,&month,&day); printf("%4d %s %d\n",day,librock_MonthNameLong[month],year); #endif /* librock_CHISEL _usesrc "acquired/sdncal/julian.c" librock_JulianToSdn librock_CHISEL _usesrc "acquired/sdncal/gregor.c" librock_GregorianToSdn librock_CHISEL _usesrc "acquired/sdncal/dow.c" librock_DayOfWeek */ /* Copyright 1998-2002 Forrest J. Cavalier III, http://www.mibsoftware.com Licensed under BSD-ish license, NO WARRANTY. Copies must retain this block. License text in librock_LIDESC_HC=12440211096131f5976d36be0cddca4cd9152e45 */ #endif /* MANUAL */ /*-------------------------------------------*/ /* Easter was calculated differently before 326 A.D. Sometime after 4099 there will need to be a correction to remove an extra leap year. */ if (year > 4099) { return 0; } if (!julian && (year < 1583)) { return 0; } if (julian) { /* Used prior to adoption of Gregorian calendar, and is still used by the Orthodox church. */ int dow; long sdnPFM = librock_JulianToSdn(year,3,1)-1+PaschalFullMoonTable[year % 19]; if (!sdnPFM) { return 0; } dow = librock_DayOfWeek(sdnPFM); return sdnPFM + (7-dow); } else { /* Gregorian From http://www.oremus.org/liturgy/etc/ktf/app/easter.html The tables which appear here and, in more detail, in the Book of Common Prayer can be used to determine the date of Easter. Underlying these tables is a relatively simple algorithm which is described here. This description assumes a limited mathematical knowledge, particularly of integer division and remainders, or modulo arithmetic. The algorithm applies to any year since the introduction of the Gregorian Calendar, which in Britain was in September 1752. We refer to the year number as y, and use it to calculate the Golden number, g: */ int g = (year % 19) + 1; /*Next we calculate the date of the Paschal full moon, that is, the full moon which Easter is the Sunday after. This is done in several stages. First we calculate two values called the solar correction, s, and the lunar correction, l. */ int s = (year - 1600) / 100 - (year - 1600) / 400 ; int l = (((year - 1400) / 100) * 8) / 25 ; /* Next we calculate an uncorrected date for the Paschal full moon, p'; then we apply a minor correction, to get the exact date, p, as the number of days after 21st March. */ int pp = (3 - (11*g) + s - l) % 30; int p; int dow; long sdnPFM; if (pp < 0) { pp += 30; } if ((pp == 29) || ((pp == 28) && (g > 11))) { p = pp - 1; } else { p = pp; } sdnPFM = librock_GregorianToSdn(year,3,21)+p; if (!sdnPFM) { return 0; } dow = librock_DayOfWeek(sdnPFM); return sdnPFM + (7-dow); } } /**************************************************************/ #endif /* NOIMP section */ /* $Log: easter.c,v $ Revision 1.8 2002/08/01 22:07:23 forrest@mibsoftware.com rights=#1 Needed #include of types.c Revision 1.7 2002/08/01 20:45:12 forrest@mibsoftware.com rights=#1 Updated TYPICAL_USE section. Added NOTLIBROCK section. Moved CVS log to end. Changed LIDESC MD5 to HC. Revision 1.6 2002/04/09 03:39:35 forrest@mibsoftware.com rights=#1 Added FNTYPEs. Updated LICENSE in manual pages. Revision 1.5 2002/02/08 12:47:56 forrest@mibsoftware.com rights=#1 Adjust comments Revision 1.4 2002/02/08 12:47:17 forrest@mibsoftware.com rights=#1 Fix LIDESC, standardized chg log Revision 1.3 2002/01/30 16:08:06 forrest@mibsoftware.com rights=#1 Renamed some .h files Revision 1.2 2002/01/29 04:44:57 forrest@mibsoftware.com rights=#1 Docs, julian check for years prior to 1583 Revision 1.1 2001/11/01 15:40:05 forrest@mibsoftware.com rights=#1 Initial rights#1 Copyright (c) Forrest J Cavalier III d-b-a Mib Software rights#1 License text in librock_LIDESC_HC=12440211096131f5976d36be0cddca4cd9152e45 */