home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.misc
- From: <dfs@doe.carleton.ca> (David F. Skoll)
- Subject: v37i030: remind - A replacement for calendar, Patch05c/3
- Message-ID: <1993Apr28.025515.3168@sparky.imd.sterling.com>
- X-Md4-Signature: 50dd5f233ab093d49f8f8d5e13ef1477
- Date: Wed, 28 Apr 1993 02:55:15 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: <dfs@doe.carleton.ca> (David F. Skoll)
- Posting-number: Volume 37, Issue 30
- Archive-name: remind/patch05c
- Environment: UNIX, MS-DOS, OS/2
- Patch-To: remind: Volume 33, Issue 58-69
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: hbcal.c
- # Wrapped by kent@sparky on Tue Apr 27 21:38:31 1993
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 3 (of 3)."'
- if test -f 'hbcal.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'hbcal.c'\"
- else
- echo shar: Extracting \"'hbcal.c'\" \(16053 characters\)
- sed "s/^X//" >'hbcal.c' <<'END_OF_FILE'
- X/***************************************************************/
- X/* */
- X/* HBCAL.C */
- X/* */
- X/* Support for the Hebrew calendar */
- X/* */
- X/* This file is part of REMIND. */
- X/* Copyright (C) 1992, 1993 by David F. Skoll. */
- X/* */
- X/* Derived from code written by Amos Shapir in 1978; revised */
- X/* 1985. */
- X/* */
- X/***************************************************************/
- X#include <stdio.h> /* For FILE used by protos.h - sigh. */
- X#include "config.h"
- X#include "types.h"
- X#include "protos.h"
- X#include "globals.h"
- X#include "err.h"
- X#define HOUR 1080L
- X#define DAY (24L*HOUR)
- X#define WEEK (7L*DAY)
- X#define M(h,p) ((long)(h*HOUR+p))
- X#define MONTH (DAY+M(12,793))
- X
- X/* Correction to convert base reference to 1990. NOTE: If you change
- X the value of BASE in config.h, this will NOT WORK! You'll have to
- X add the appropriate number of days to CORRECTION. */
- X
- X#define CORRECTION 732774L
- X
- X#define TISHREY 0
- X#define HESHVAN 1
- X#define KISLEV 2
- X#define TEVET 3
- X#define SHVAT 4
- X#define ADARA 5
- X#define ADARB 6
- X#define NISAN 7
- X#define IYAR 8
- X#define SIVAN 9
- X#define TAMUZ 10
- X#define AV 11
- X#define ELUL 12
- X#define ADAR 13
- X
- X#define JAHR_NONE 0
- X#define JAHR_FORWARD 1
- X#define JAHR_BACKWARD 2
- X
- Xstatic char *HebMonthNames[] = {
- X "Tishrey", "Heshvan", "Kislev", "Tevet", "Shvat", "Adar A", "Adar B",
- X "Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul", "Adar"};
- X
- Xstatic char MaxMonLen[] = {
- X 30, 30, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 29};
- X
- Xstatic char HebIsLeap[] = {0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,1};
- X
- X/***************************************************************/
- X/* */
- X/* RoshHashana */
- X/* */
- X/* Return the Julian date for Rosh Hashana of specified */
- X/* Hebrew year. (ie, 5751, not 1990) */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int RoshHashana(int i)
- X#else
- Xint RoshHashana(i)
- Xint i;
- X#endif
- X{
- X long j;
- X j = DaysToHebYear(i-3744) - CORRECTION;
- X return (int) j; /* No overflow check... very trusting! */
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DaysToHebYear */
- X/* */
- X/* Return the number of days to RH of specified Hebrew year */
- X/* from new moon before Tishrey 1 5701. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC long DaysToHebYear(int y)
- X#else
- Xlong DaysToHebYear(y)
- Xint y;
- X#endif
- X{
- X long m, nm, dw, s, l;
- X
- X l = y*7+1; /* no. of leap months */
- X m = y*12+l/19; /* total no. of months */
- X nm = m*MONTH+M(1,779); /* molad at 197 cycles */
- X s = m*28+nm/DAY-2;
- X
- X nm %= WEEK;
- X l %= 19L;
- X dw = nm/DAY;
- X nm %= DAY;
- X
- X /* special cases of Molad Zaken */
- X if (nm >= 18*HOUR ||
- X (l < 12 && dw==3 && nm>=M(9,204)) ||
- X (l < 7 && dw==2 && nm>=M(15,589)))
- X s++,dw++;
- X /* ADU */
- X if(dw == 1 || dw == 4 || dw == 6)
- X s++;
- X return s;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DaysInHebYear */
- X/* */
- X/* Return the number of days in the Hebrew year. */
- X/* */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int DaysInHebYear(int y)
- X#else
- Xint DaysInHebYear(y)
- Xint y;
- X#endif
- X{
- X long thisyear, nextyear;
- X
- X thisyear = DaysToHebYear(y-3744);
- X nextyear = DaysToHebYear(y-3743);
- X return (int) (nextyear - thisyear);
- X}
- X
- X/***************************************************************/
- X/* */
- X/* DaysInHebMonths */
- X/* */
- X/* Return a pointer to an array giving lengths of months */
- X/* given the LENGTH of the Hebrew year. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC char *DaysInHebMonths(int ylen)
- X#else
- Xchar *DaysInHebMonths(ylen)
- Xint ylen;
- X#endif
- X{
- X static char monlen[13] =
- X {30, 29, 30, 29, 30, 0, 29, 30, 29, 30, 29, 30, 29};
- X
- X
- X if (ylen > 355) {
- X monlen[ADARA] = 30;
- X ylen -= 30;
- X } else monlen[ADARA] = 0;
- X
- X if (ylen == 353) monlen[KISLEV] = 29; else monlen[KISLEV] = 30;
- X if (ylen == 355) monlen[HESHVAN] = 30; else monlen[HESHVAN] = 29;
- X
- X return monlen;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* HebToJul */
- X/* */
- X/* Convert a Hebrew date to Julian. */
- X/* Hebrew months range from 0-12, but Adar A has 0 length in */
- X/* non-leap-years. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int HebToJul(int hy, int hm, int hd)
- X#else
- Xint HebToJul(hy, hm, hd)
- Xint hy, hm, hd;
- X#endif
- X{
- X int ylen;
- X char *monlens;
- X int rh;
- X int m;
- X
- X /* Do some range checking */
- X if (hy - 3761 < BASE || hy - 3760 > BASE+YR_RANGE) return -1;
- X
- X ylen = DaysInHebYear(hy);
- X monlens = DaysInHebMonths(ylen);
- X
- X /* Get the Rosh Hashana of the year */
- X rh = RoshHashana(hy);
- X
- X /* Bump up to the appropriate month */
- X for (m=0; m<hm; m++) rh += monlens[m];
- X
- X /* Add in appropriate number of days */
- X rh += hd - 1;
- X return rh;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* JulToHeb */
- X/* */
- X/* Convert a Julian date to Hebrew. */
- X/* Hebrew months range from 0-12, but Adar A has 0 length in */
- X/* non-leap-years. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC void JulToHeb(int jul, int *hy, int *hm, int *hd)
- X#else
- Xvoid JulToHeb(jul, hy, hm, hd)
- Xint jul, *hy, *hm, *hd;
- X#endif
- X{
- X int y, m, d;
- X int rh;
- X int ylen;
- X char *monlen;
- X /* Get the common year */
- X FromJulian(jul, &y, &m, &d);
- X y += 3763; /* Over-estimate a bit to be on the safe side below... */
- X
- X /* Find the RH just before desired date */
- X while ((rh=RoshHashana(y))>jul) y--;
- X
- X /* Got the year - now find the month */
- X jul -= rh;
- X ylen = DaysInHebYear(y);
- X monlen = DaysInHebMonths(ylen);
- X m = 0;
- X while((jul > monlen[m]) || !monlen[m]) {
- X jul -= monlen[m];
- X m++;
- X }
- X
- X *hy = y;
- X *hm = m;
- X *hd = jul+1;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* HebNameToNum */
- X/* */
- X/* Convert a Hebrew month's name to its number, given the */
- X/* year. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int HebNameToNum(const char *mname)
- X#else
- Xint HebNameToNum(mname)
- Xchar *mname;
- X#endif
- X{
- X int i;
- X int m=-1;
- X
- X for (i=0; i<14; i++)
- X if (!StrCmpi(mname, HebMonthNames[i])) {
- X m = i;
- X break;
- X }
- X
- X return m;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* HebMonthname */
- X/* */
- X/* Convert a Hebrew month's number to its name, given the */
- X/* year. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC char *HebMonthName(int m, int y)
- X#else
- Xchar *HebMonthName(m, y)
- Xint m, y;
- X#endif
- X{
- X if (m != ADARA && m != ADARB) return HebMonthNames[m];
- X
- X if (!HebIsLeap[(y-1)%19]) return HebMonthNames[ADAR];
- X else return HebMonthNames[m];
- X}
- X
- X/***************************************************************/
- X/* */
- X/* GetValidHebDate */
- X/* */
- X/* Given the day of a month, a Hebrew month number, and a */
- X/* year, return a valid year number, month number, and day */
- X/* number. Returns 0 for success, non-0 for failure. */
- X/* If *dout is set to -1, then date is completely invalid. */
- X/* Otherwise, date is only invalid in specified year. */
- X/* */
- X/* Algorithm: */
- X/* - Convert references to Adar to Adar B. */
- X/* If jahr == 0 then */
- X/* - If no such date in current Hebrew year, return */
- X/* failure. */
- X/* else follow jahrzeit rules: */
- X/* - If jahr == 1: Convert 30 Kislev to 1 Tevet and */
- X/* 30 Heshvan to 1 Kislev if chaser. */
- X/* Convert 30 Adar A to 1 Nisan in nonleap */
- X/* This rule is NOT appropriate for a */
- X/* jahrzeit on 30 Adar A. Use rule 2 for */
- X/* that. However, I believe it is correct */
- X/* for smachot. */
- X/* - If jahr == 2: Convert 30 Kislev to 29 Kislev and */
- X/* 30 Heshvan to 29 Heshvan if chaser. */
- X/* Change 30 Adar A to 30 Shvat in nonleap */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int GetValidHebDate(int yin, int min, int din,
- X int *mout, int *dout, int jahr)
- X#else
- Xint GetValidHebDate(yin, min, din, mout, dout, jahr)
- Xint yin, min, din, *mout, *dout, jahr;
- X#endif
- X{
- X char *monlen;
- X int ylen;
- X
- X *mout = min;
- X *dout = din;
- X
- X /* Do some error checking */
- X if (din < 1 || din > MaxMonLen[min] || min < 0 || min > 13) {
- X *dout = -1;
- X Eprint("Invalid Hebrew date");
- X return E_BAD_DATE;
- X }
- X
- X /* Convert ADAR to ADAR-B */
- X if (min == ADAR) *mout = min = ADARB;
- X
- X ylen = DaysInHebYear(yin);
- X monlen = DaysInHebMonths(ylen);
- X
- X if (din <= monlen[min]) return OK;
- X
- X switch(jahr) {
- X case JAHR_NONE: return E_BAD_DATE;
- X
- X case JAHR_FORWARD:
- X if (min == KISLEV) {
- X *mout = TEVET;
- X *dout = 1;
- X return OK;
- X } else if (min == HESHVAN) {
- X *mout = KISLEV;
- X *dout = 1;
- X return OK;
- X } else if (min == ADARA) {
- X if (din > 29) {
- X *dout = 1;
- X *mout = NISAN;
- X } else {
- X *dout = din;
- X *mout = ADARB;
- X }
- X return OK;
- X }
- X
- X Eprint("GetValidHebDate: (1) software error! %d", jahr);
- X return E_SWERR;
- X
- X case JAHR_BACKWARD:
- X if (min == KISLEV) {
- X *mout = KISLEV;
- X *dout = 29;
- X return OK;
- X } else if (min == HESHVAN) {
- X *mout = HESHVAN;
- X *dout = 29;
- X return OK;
- X } else if (min == ADARA) {
- X if (din > 29) {
- X *dout = 30;
- X *mout = SHVAT;
- X } else {
- X *mout = ADARB;
- X *dout = din;
- X }
- X return OK;
- X }
- X
- X Eprint("GetValidHebDate: (2) software error! %d", jahr);
- X return E_SWERR;
- X
- X default:
- X Eprint("GetValidHebDate: (3) software error! %d", jahr);
- X return E_SWERR;
- X }
- X}
- X
- X
- X/***************************************************************/
- X/* */
- X/* GetNextHebrewDate */
- X/* */
- X/* Get the next Hebrew date on or after specified date. */
- X/* */
- X/* Returns 0 for success, non-zero for failure. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int GetNextHebrewDate(int julstart, int hm, int hd, int jahr, int *ans)
- X#else
- Xint GetNextHebrewDate(julstart, hm, hd, jahr, ans)
- Xint julstart, hm, hd, jahr, *ans;
- X#endif
- X{
- X int r, yout, mout, dout, jul;
- X
- X JulToHeb(julstart, &yout, &mout, &dout);
- X
- X r = 1;
- X while(r) {
- X r = GetValidHebDate(yout, hm, hd, &mout, &dout, jahr);
- X if (dout == -1) return r;
- X if (r) {
- X yout++;
- X continue;
- X }
- X jul = HebToJul(yout, mout, dout);
- X if (jul >= julstart) break;
- X else {
- X yout++;
- X r=1; /* Force loop to continue */
- X }
- X }
- X *ans = jul;
- X return OK;
- X}
- X
- X/***************************************************************/
- X/* */
- X/* ComputeJahr */
- X/* */
- X/* Given a date of death, compute the value to use for jahr. */
- X/* */
- X/***************************************************************/
- X#ifdef HAVE_PROTOS
- XPUBLIC int ComputeJahr(int y, int m, int d, int *ans)
- X#else
- Xint ComputeJahr(y, m, d, ans)
- Xint y, m, d, *ans;
- X#endif
- X{
- X char *monlen;
- X int len;
- X
- X *ans = JAHR_NONE;
- X
- X len = DaysInHebYear(y);
- X monlen = DaysInHebMonths(len);
- X
- X/* Check for Adar A */
- X if (m == ADARA && monlen[m] == 0) {
- X Eprint("No Adar A in %d", y);
- X return E_BAD_DATE;
- X }
- X
- X
- X if (d < 1 || d > MaxMonLen[m] || m < 0 || m > 13) {
- X Eprint("Invalid Hebrew date");
- X return E_BAD_DATE;
- X }
- X
- X if (d > monlen[m]) {
- X Eprint("No %d %s %d", d, HebMonthNames[m], y);
- X return E_BAD_DATE;
- X }
- X
- X/* If the jahrzeit was in Adar A, we always use JAHR_BACKWARD */
- X if (m == ADARA) {
- X *ans = JAHR_BACKWARD;
- X return OK;
- X }
- X
- X/* Get lengths of months in year following jahrzeit */
- X len = DaysInHebYear(y+1);
- X monlen = DaysInHebMonths(len);
- X
- X if (d > monlen[m]) *ans = JAHR_FORWARD;
- X else *ans = JAHR_BACKWARD;
- X
- X return OK;
- X}
- END_OF_FILE
- if test 16053 -ne `wc -c <'hbcal.c'`; then
- echo shar: \"'hbcal.c'\" unpacked with wrong size!
- fi
- # end of 'hbcal.c'
- fi
- echo shar: End of archive 3 \(of 3\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-