Here's the main bit of code; the two documents from which I derived it
are over the 40k limit. One is the calendar FAQ text version. The other
is a file easter_date.txt that is a thread from:
Newsgroups: soc.religion.christian
From: mls@sfsup.att.com (Mike Siemon)
Subject: Easter algorithms I
Organization: AT&T Bell Laboratories
Approved: christian@aramis.rutgers.edu
Does anyone want such files?
Anyway, the implemented formulas are below. The header files are just
for keeping track of Palm-specific variables for different modules.
/*****************************************************************************
*
* Created with Falch.net DeveloperStudio
* http://www.falch.net/
*
* Created : 4/11/01 12:18:42 AM
* Creator : (Unknown)
*
****************************************************************************/
#include
#include "Easter.h"
#include "Easter_res.h"
extern Boolean England;
extern UInt16 YearAD;
Char Orthodox_Julian[20], Orthodox_Gregorian[20], Western[20];
typedef enum {Julian,Gregorian} calendar;
/* The "Golden Number" is the order of the year in the 19-year lunar
cycle.
* It is the same in Julian or Gregorian calendars, and is listed in the
* output of this program under the heading GN.
*/
int GoldenNumber(int year)
{
return ((year % 19) + 1);
}
/* All dates in this program are referred to March 1st; so 32 means
* April 1 and 0 means February 28th or 29th. Leap years are needed
* for printing February dates (and for dominical letters).
*/
int Leap(int year, calendar style)
{
if (year % 4)
return 0;
else switch(style) {
case Julian: return 1;
case Gregorian: return (year % 100 || year % 400 == 0);
}
}
#define century (year/100)
/* Gregorian solar correction -- this is the number of days difference
* between Julian and Gregorian civil dates, in effect the number of
* excess leap years in the Julian calendar since the time of Nicea.
* This correction derives from the Gregorian introduction of non-leap
* century years, giving mean tropical year = 365.2425 days.
*/
int Solar(int year)
{
return (century - century/4 - 2);
}
/* Gregorian lunar correction -- this is only used for the computation
of
* the paschal new moon (via epact), but might as well be pulled out on
* its own. I give the pedantically correct version.
* This correction derives from the mean lunar month being 29.53059 days
* instead of the 6939.75/235 assumed in the Julian calendar. It is one
* days in (roughly) 312.5 years, or 8 days in 2500 years.
*/
int Lunar(int year)
{
return ((century - 15 - (century-17)/25)/3);
}
/* Epact is the "age" of the moon on March 1st (same as January 1st);
* It (may have) derived from Greek methods of calculating the extra
* ("epagomenal") months intercalated into the regular 12 at 7 points
* of the 19-year Metonic cycle. However, it is not used in Julian
* easter calculations and is provided here only for Gregorian NewMoon.
*/
int Epact(int year)
{
int epact;
epact = (11*GoldenNumber(year) - Solar(year) + Lunar(year)) % 30;
if (epact < 0)
epact += 30;
return epact;
}
/* Here's the hard one. Keep in mind that there are several artificial
* conventions -- the equinox is ALWAYS March 21; new moon is ALWAYS the
* date on which a fictitious "average" moon is one day old, and the
full
* moon is 13 days later, on the 14th of the month. In the Julian
version
* (and MOSTLY in the Gregorian) the pre-paschal month has 30 days. All
* of this works out keeping fairly close to astronomical reality in the
* Gregorian case, but it is not necessarily exact.
*/
int NewMoon(int year, calendar style)
{
int new_moon, epact;
switch (style) {
case Julian:
new_moon = (4 - 11*GoldenNumber(year)) % 30;
while (new_moon < 8)
new_moon += 30;
return new_moon;
case Gregorian:
epact = Epact(year);
new_moon = 31-epact;
if (new_moon < 8) {
new_moon += 30;
if (epact == 24 || epact == 25 && year%19 > 10)
new_moon--;
}
return new_moon;
}
}
int WeekDay(int date, int year, calendar style)
{
int d;
d = date + year + year/4;
if (style == Gregorian)
d -= Solar(year);
return (d % 7);
}
/* Given the Paschal full moon, we just step to the next Sunday ...
*/
int Easter(int year, calendar style)
{
int paschal_moon;
paschal_moon = NewMoon(year, style) + 13;
return (paschal_moon + 7 - WeekDay(paschal_moon, year, style));
}
/* The rest of the code turns numbers into human-readable output */
static Boolean frmDates_fldOrthodoxJulian_OnSelect(EventPtr event)
{
// Insert code for fldOrthodoxJulian
FormPtr form;
FieldPtr field;
form = FrmGetActiveForm();
field =
FrmGetObjectPtr(form,FrmGetObjectIndex(form,fldOrthodoxJulian));
FldCopy(field);
return true;
}
static Boolean frmDates_fldOrthodoxGregorian_OnSelect(EventPtr event)
{
// Insert code for fldOrthodoxGregorian
FormPtr form;
FieldPtr field;
form = FrmGetActiveForm();
field =
FrmGetObjectPtr(form,FrmGetObjectIndex(form,fldOrthodoxGregorian));
FldCopy(field);
return true;
}
static Boolean frmDates_fldWesternGregorian_OnSelect(EventPtr event)
{
// Insert code for fldWesternGregorian
FormPtr form;
FieldPtr field;
form = FrmGetActiveForm();
field =
FrmGetObjectPtr(form,FrmGetObjectIndex(form,fldWesternGregorian));
FldCopy(field);
return true;
}
static Boolean frmDates_cmdNewYear_OnSelect(EventPtr event)
{
// Insert code for cmdNewYear
FrmGotoForm(frmMain);
return true;
}
Boolean frmDates_HandleEvent(EventPtr event)
{
FormPtr form;
FieldPtr J1, J2, G;
Boolean handled = false;
int year, easterJ1, easterJ2, easterG;
switch (event->eType)
{
case ctlSelectEvent:
switch (event->data.ctlSelect.controlID)
{
// fldOrthodoxJulian receives an event
case fldOrthodoxJulian:
handled = frmDates_fldOrthodoxJulian_OnSelect(event);
break;
// fldOrthodoxGregorian receives an event
case fldOrthodoxGregorian:
handled = frmDates_fldOrthodoxGregorian_OnSelect(event);
break;
// fldWesternGregorian receives an event
case fldWesternGregorian:
handled = frmDates_fldWesternGregorian_OnSelect(event);
break;
// cmdNewYear receives an event
case cmdNewYear:
handled = frmDates_cmdNewYear_OnSelect(event);
break;
}
break;
case frmOpenEvent:
form = FrmGetActiveForm();
J1 = FrmGetObjectPtr(form,FrmGetObjectIndex(form,fldOrthodoxJulian));
J2 =
FrmGetObjectPtr(form,FrmGetObjectIndex(form,fldOrthodoxGregorian));
G =
FrmGetObjectPtr(form,FrmGetObjectIndex(form,fldWesternGregorian));
// Calculate the necessary dates
year = (int) YearAD;
easterJ1 = Easter(year, Julian);
easterJ2 = easterJ1 + Solar(year);
easterG = Easter(year, Gregorian);
if (easterJ1 > 31)
StrPrintF(Orthodox_Julian, "%2d April AD %d", easterJ1-31, year);
else
StrPrintF(Orthodox_Julian, "%2d March AD %d", easterJ1, year);
if (easterJ2 > 92)
StrPrintF(Orthodox_Gregorian, "%2d June AD %d", easterJ2-92, year);
else if (easterJ2 > 61)
StrPrintF(Orthodox_Gregorian, "%2d May AD %d", easterJ2-61, year);
else if (easterJ2 > 31)
StrPrintF(Orthodox_Gregorian, "%2d April AD %d", easterJ2-31, year);
else
StrPrintF(Orthodox_Gregorian, "%2d March AD %d", easterJ2, year);
if (easterG > 31)
StrPrintF(Western, "%2d April AD %d", easterG-31, year);
else
StrPrintF(Western, "%2d March AD %d", easterG, year);
if (year < 1583)
{
FldSetTextPtr(J1,Orthodox_Julian);
FldSetTextPtr(J2,"");
FldSetTextPtr(G,"");
}
else if (year < 1753 && England)
{
FldSetTextPtr(J1,Orthodox_Julian);
FldSetTextPtr(J2,Orthodox_Gregorian);
FldSetTextPtr(G,"");
}
else
{
FldSetTextPtr(J1,Orthodox_Julian);
FldSetTextPtr(J2,Orthodox_Gregorian);
FldSetTextPtr(G,Western);
}
// Repaint form on open
FrmDrawForm(form);
handled = true;
break;
}
return handled;
}
On Sun, 2008-06-22 at 19:38 +0200, Hans Hagen wrote:
Charles P. Schaum wrote:
Some calendar links, FYI:
http://astro.nmsu.edu/~lhuber/leaphist.html
http://www.smart.net/~mmontes/ec-cal.html
http://www.tondering.dk/claus/calendar.html
http://tycho.usno.navy.mil/vphase.html
I would be happy to make available the C code for an Easter date
calculator that I implemented on the Palm III. I used the complex
algorithm that figures the "age" of the moon at New Year's. It
originally came from Bell Labs, I think.
well, we can make a nice l-calendar.lua module together
just provide me the calculations (i can implement to lua code but i have
no time to figure out all the logic)
Hans
-----------------------------------------------------------------
Hans Hagen | PRAGMA ADE
Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
tel: 038 477 53 69 | fax: 038 477 53 74 | www.pragma-ade.com
| www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
archive : https://foundry.supelec.fr/projects/contextrev/
wiki : http://contextgarden.net
___________________________________________________________________________________