buz@ucla-cs.UUCP (04/02/87)
: 'for poor Xenix systems' #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh or : line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # datelib.c # easter.c # holidays.c # This archive created: Wed Apr 1 14:57:44 1987 export PATH; PATH=/bin:$PATH echo shar: extracting "'datelib.c'" '(10205 characters)' if test -f 'datelib.c' then echo shar: will not over-write existing file "'datelib.c'" else sed 's/^ X//' << \SHAR_EOF > 'datelib.c' X X X/* DATELIB -- LIBRARY FUNCTIONS FOR UNIX DATES */ X/* */ X/* Copyright (c) 1987 Tigertail Associates. All Rights Reserved */ X/* 320 North Bundy Drive */ X/* Los Angeles, California 90049 */ X/* USA */ X/* */ X/* e-mail: (uucp) ucla-cs!buz or (arpa) buz@cs.ucla.edu */ X/* */ X X#include <time.h> X#include "taxc.h" X X#define DAY (24L*3600L) X#define YEAR (DAY*365L) /* in seconds */ X#define RYEAR 31556926L /* 365.2422 * DAY */ X#define NERA (56*YEAR+14*DAY) /* 56 years and 14 leap days */ X X#ifdef BSD X#define TZONE ((TZV)*3600) /* in seconds west of greenwich */ Xlong time(); Xstruct tm *localtime(); X#else Xextern long timezone; Xextern Bool daylight; X#endif X X/* This library provides the following functions */ X#if defined(lint) || defined(BSD) || defined(SYSV) Xlong uxdate(), uxldate(), uxtime(), uxeaster(); Xint yrday(), weeknum(), daynum(); XBool leap(); Xvoid datex(), ldatex(), timex(); X#else Xlong uxdate(int,int,int), uxldate(int,int,int), uxtime(int,int,int); Xlong uxeaster(int); Xint yrday(int,int,int), weeknum(long), daynum(long); XBool leap(int); Xvoid datex(long,int*,int*,int*,int*,int*); Xvoid ldatex(long,int*,int*,int*,int*,int*); Xvoid timex(long,int*,int*,int*); X#endif X X/* This external array is sometimes handy */ Xint monthdays[] = { 0, 31, 59, 90, 120, 151, 181, X 212, 243, 273, 304, 334, 365 }; X X/* Function uxdate X * Return the number of seconds between Jan 1, 1970 and the X * 0h 0m 0s of the date pm/pd/py in the current unix era. X * The date can be viewed as Greenwich date or it can be viewed X * as an abstract date, if you need to combine it with time it X * needs correction for the timezone and daylight savings time. X * The year is the full christian year, 70 is nonsense (and not X * in the current era anyway, it is not interpreted as the year X * 1970. Calculation is only done for the Gregorian calendar. X * X * A unix date is assumed to be signed and represent dates before X * 1970 -- this is contrary to some speculation. Using this scheme X * unix dates cover an era from about 1903 to about 2032. Beyond this X * other reperesentations need to be used. The alternative is to X * consider unix dates as unsigned longs. Using that scheme no date X * before 1970 can be represented; these programs use signed longs X * with a beginning era of 1914. X */ X Xlong PROC uxdate ( py, pm, pd ) Xint py, pm, pd; X X{ long yrs = (py-1970L); /* Number of years from 0h 1970 */ X long nd = yrs * 365L; /* Number of days in those years */ X X if ( yrs >= 0 ) /* Add in bygone leap days */ X then nd += ((yrs+1L) / 4L); X else nd += ((yrs-2L) / 4L); X X if ( pm > 2 ) /* Leap year correction for this year */ X then nd += leap(py); X X /* ( base + prior months + this month ) * sec/day */ X return ( ( nd + monthdays[pm-1] + pd - 1 ) * DAY ); X} X X X X/* Function uxldate X * Return the number of seconds between GMT Jan 1, 1970 0h 0m 0s X * and local time 0h 0m 0s of date pm/pd/py in the current era. X * The date is thus based on local time. The year is the full year, X * `70' is nonsense not the year `1970'. Calculation is Gregorian X * calendar for the current era. X */ X Xlong PROC uxldate ( py, pm, pd) Xint py, pm, pd; X X{ long n; X#ifdef BSD X struct tm *tp; X tp = localtime(); X n = uxdate ( py, pm, pd ) + (TZONE - (tp->tm_isdst ? 3600L : 0L)); X#else X tzset(); X n = uxdate ( py, pm, pd ) + (timezone - (daylight ? 3600L : 0L)); X#endif X return (n); X} X X X X/* Routine datex (date extraction). The opposite function of uxdate; X * that is, break down a Unix date into: X * cy current christian year 1903 .. 2036 X * cm number full months so far this year 0 .. 11 where 0 = Jan X * cyd number full days so far this year 0 .. 365 where 0 = Jan 1st X * cmd number full days so far this month 0 .. 30 where 0 = 1st X * cwd number full days so far this week 0 .. 6 where 0 = Sun X * This provides almost the same functions as the system provided gmtime X * without static storage pointers (considered dirty). X * See timex for time extraction. X */ X Xvoid PROC datex ( udate, cy, cm, cyd, cmd, cwd ) Xlong udate; Xint *cy, *cm, *cyd, *cmd, *cwd; X X{ long xd; /* modified date -- copy to muck around with */ X long csy; /* current start of year in seconds */ X int nld; /* number of leap days to start of year */ X long nlds; /* number of leap days to start of year in seconds */ X int xy; /* x number of full years since 1970 */ X int yd, md, wd; /* day of year, month, and week */ X int am, rm; /* approx. month, real month */ X int tld=0; /* temporary leap day correction in days */ X Bool tly; /* is leap day */ X int era; /* starting year of date sequence */ X X if ( udate < 0 ) X then X { era = 1914; /* Calendar & LY orientation == 1970 */ X xd = NERA + udate; } X else X { era = 1970; X xd = udate; } X X nld = (xd+YEAR+306*DAY)/(4L*YEAR+DAY); /* leap days in era incl. now */ X nlds = nld * DAY; X xy = (xd-nlds) / YEAR; /* Years from origin (yrs) */ X *cy = era + xy; /* Return year */ X X csy = xy*YEAR + ((xy+1)/4) * DAY; /* Start of this year in sec */ X yd = ((xd - csy) / DAY); /* Full days so far this year in days */ X /* printf ( "csy=%ld, yd=%d, cy=%d, ", csy/DAY, yd, *cy ); */ X if ( tly = leap(*cy) ) /* If this year a leap year */ X then tld = (yd>=60) ? 1 : 0; /* Adjust for it; 2 makes Mar work */ X else tld = 0; X X /* printf ( "nld=%d, xy=%d, xd=%ld, ", nld, xy, xd/DAY ); */ X /* printf ( "tld=%d, csy=%ld, yd=%d\n", tld, csy/DAY, yd ); */ X X *cyd = yd; /* Return full days so far this year */ X am = (yd-tld) / 29; /* Approximate current month 0-12 */ X if ( (yd-tld) < monthdays[am] ) /* Determine real month 0-11 */ X then rm = am - 1; X else rm = am; X if (tly&&(yd==59)) then rm = 1; /* Fix leap day (Ugh) */ X *cm = rm; /* Return full months in year so far */ X X md = yd - monthdays[rm] - tld;/* Full days in month so far */ X *cmd = md; /* Return full days in month so far */ X X wd = ( 4L + ( xd / DAY )) % 7; /* in days */ X *cwd = wd; /* Return full days in week so far */ X X return; X} X X X X/* Routine ldatex (date extraction). The opposite function of uxldate; X * that is, break down a local time Unix date into the same things as datex. X */ X Xvoid PROC ldatex ( udate, cy, cm, cyd, cmd, cwd ) Xlong udate; Xint *cy, *cm, *cyd, *cmd, *cwd; X X{ long ud; X#ifdef BSD X struct tm *tp; X tp = localtime(); X ud = udate - (TZONE - (tp->tm_isdst ? 3600L : 0L)); X datex( ud, cy, cm, cyd, cmd, cwd ); X#else X tzset(); X ud = udate - (timezone - (daylight ? 3600L : 0L)); X datex( ud, cy, cm, cyd, cmd, cwd ); X#endif X return; X} X X X/* Function uxtime X * Convert a broken-down local time ph:pm:ps to X * seconds since local midnight. X */ X X Xlong PROC uxtime ( ph, pm, ps ) Xint ph, pm, ps; X X{ return ( ph * 3600L + pm * 60L + ps ); X} X X X X X/* Routine timex. Do the opposite of uxtime take a Unix time X * and return: X * ch number of full hours since midnight X * cm number of full minutes since last hour X * cs number of full seconds since last minute X */ X Xvoid PROC timex ( udate, ch, cm, cs ) Xlong udate; Xint *ch, *cm, *cs; X X{ long ct = (udate<0?NERA+udate:udate); /* Make date/time positive */ X ct %= DAY; /* get rid of the days part */ X *ch = ct / 3600L; /* get the hours out */ X *cm = (int)(ct-(*ch)*3600L) / 60; /* get the minutes out */ X *cs = ct % 60; /* get the seconds out */ X return; X} X X X X/* Function uxeaster X * Given a year (eg 1984) it provides a Unix date X * for 0h Easter of that year. X */ X X Xlong PROC uxeaster ( py ) Xint py; X X{ /* The following amusing algorithm comes from page 5 of X * <Practical Astronomy with your calculator>, second edition, X * by Peter Duffett-Smith, Cambridge University Press, 1979, 1981. X * The truth of the algorithm is self evident. X */ X X int a = py % 19; X int b = py / 100; X int c = py % 100; X int d = b / 4; X int e = b % 4; X int f = (b + 8) / 25; X int g = (b - f + 1) / 3; X int h = (19*a + b - d - g + 15) % 30; X int i = c / 4; X int k = c % 4; X int l = (32 + 2*e + 2*i - h - k) % 7; X int m = (a + 11*h + 22*l) / 451; X int t = (h + l - 7*m + 114); X int n = t / 31; X int p = t % 31; X X return ( uxdate( py, n, p+1 ) ); X} X X X/* X * Function yrday X * Gives the number of full days so far this year for a given date. X * Returns an int. Excludes today so Jan 1st = 0; X */ X Xint PROC yrday ( y, m, d ) Xint y, m, d; X X{ return ( monthdays[m-1] + (m>2?leap(y):0) + d-1); X /* days to month + leap day + month day */ X} X X X X/* Function leap X * Return 1 if `y' is a leap year, 0 otherwise. X */ X Xint PROC leap (y) Xint y; X X{ if (y % 400 == 0) then return (1); X if (y % 100 == 0) then return (0); X return ( ((y % 4 == 0) ? 1 : 0) ); X} X X X X/* Function weeknum X * Return the number of full Saturdays so far this month (0-5). X */ X Xint PROC weeknum ( udate ) Xlong udate; X X{ int y, m, dy, dm, dw; /* breakdown of udate from datex */ X X datex ( udate, &y, &m, &dy, &dm, &dw ); X return ( (dm + (dw - dm + 35) % 7) / 7); X} X X X X/* Function daynum X * Return the number of full days that are the same weekday so far X * this month (0-4). e.g. If date is the 3rd Tuesday of Sept. ... X * Function returns 2; X */ X Xint PROC daynum ( udate ) Xlong udate; X X{ int y, m, dy, dm, dw; /* breakdown of udate from datex */ X X datex ( udate, &y, &m, &dy, &dm, &dw ); X return ( dm / 7 ); X} SHAR_EOF if test 10205 -ne "`wc -c < 'datelib.c'`" then echo shar: error transmitting "'datelib.c'" '(should have been 10205 characters)' fi fi # end of overwriting check echo shar: extracting "'easter.c'" '(4367 characters)' if test -f 'easter.c' then echo shar: will not over-write existing file "'easter.c'" else sed 's/^ X//' << \SHAR_EOF > 'easter.c' X X/********************************************************************* X * X * Easter Service Routine X * X * X * Program Copyright (c) 1987 Tigertail Associates. All rights reserved. X * X * X * Synopsis: X * easter [year] X * X * If no year is specified then the date of the next Easter is printed. X * If a year is specified then the date of Easter that year is printed. X * X *********************************************************************/ X X#include <stdio.h> X#include <sys/types.h> X#include <time.h> X#include "taxc.h" X X#define DAY (24L*3600L) X X X/********************************************************************* X * X * Miscellaneous GLOBAL Values: X * X *********************************************************************/ X Xchar *usage[] = { "usage: %s year", X NULLS, }; X Xchar *myname; /* how program was invoked */ X Xint yrday(); Xint easter(); X X/************************************************************************ X * X * main -- Calculate Date of Easter for a given year X * X ************************************************************************/ X Xint PROC main (argc, argv) X int argc; X char **argv; X X{ int y, ed, mday, month; X static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun" }; X long time(), now; X char j; X struct tm *localtime(), *gmtime(), *tp; X X/********************************************************************* X * X * Get year: X * X *********************************************************************/ X X myname = *argv; X X if (argc > 2) /* too many args given */ X then Usage(); X X now = time( (long *)0 ); X tp = localtime( &now ); X y = tp->tm_year + 1900; X X if ( argc == 2 ) X then sscanf ( argv[1], " %d%c", &y, &j ); X X if ( y < 1583 ) X then X { printf ( "Gregorian Easter %d is undefined. ", y ); X printf ( "Gregorian calendar did not exist.\n" ); X return ( 0 ); X } X X ed = easter ( y ); X X if ( (argc < 2) && (yrday(y,ed/100,ed%100) < tp->tm_yday)) X then ed = easter ( ++y ); X X month = ed / 100; X mday = ed % 100; X printf( "Easter %d is %s %d", y, months[month-1], mday ); X if ( y < 1753 ) X then printf ( " Gregorian calendar\n" ); X else printf ( "\n" ); X X X/********************************************************************* X * X * Finish up: X * X *********************************************************************/ X X return (0); X X} /* main */ X X X X/********************************************************************* X * X * Procedure easter X * X * Given a year (eg 1984) it provides a date for Easter 422. X * X *********************************************************************/ X X Xint PROC easter ( py ) Xint py; X X{ /* The following amusing algorithm comes from page 5 of X * <Practical Astronomy with your calculator>, second edition, X * by Peter Duffett-Smith, Cambridge University Press, 1979, 1981. X * X * Returns: 323 for March 23. X * Returns: 402 for April 2. X */ X X int a = py % 19; X int b = py / 100; X int c = py % 100; X int d = b / 4; X int e = b % 4; X int f = (b + 8) / 25; X int g = (b - f + 1) / 3; X int h = (19*a + b - d - g + 15) % 30; X int i = c / 4; X int k = c % 4; X int l = (32 + 2*e + 2*i - h - k) % 7; X int m = (a + 11*h + 22*l) / 451; X int t = (h + l - 7*m + 114); X int n = t / 31; X int p = t % 31; X X return ( n*100 + (p+1) ); X} X X X X/************************************************************************ X * X * USAGE X * X * Print usage messages (char *usage[]) to stderr and exit nonzero. X * Each message is followed by a newline. X * X ************************************************************************/ X XPROC Usage() X{ X register int which = 0; /* current line */ X X while (usage [which] != NULLS) X { fprintf (stderr, usage [which++], myname); X putc ('\n', stderr); X } X X exit (1); X X} /* Usage */ X X X/************************************************************************ X * X * Error X * X * Print an error message to stderr and exit nonzero. Message is preceded X * by "<myname>: " using global char *myname, and followed by a newline. X * X ************************************************************************/ X X/* VARARGS */ XPROC Error (message, arg1, arg2, arg3, arg4) X char *message; X long arg1, arg2, arg3, arg4; X X{ fprintf (stderr, "%s: ", myname); X fprintf (stderr, message, arg1, arg2, arg3, arg4); X putc ('\n', stderr); X X exit (1); X X} /* Error */ X SHAR_EOF if test 4367 -ne "`wc -c < 'easter.c'`" then echo shar: error transmitting "'easter.c'" '(should have been 4367 characters)' fi fi # end of overwriting check echo shar: extracting "'holidays.c'" '(30663 characters)' if test -f 'holidays.c' then echo shar: will not over-write existing file "'holidays.c'" else sed 's/^ X//' << \SHAR_EOF > 'holidays.c' X X X/********************************************************************* X * X * A Christian and Holiday Calandar Routine X * X * X * Program Copyright (c) 1987 Tigertail Associates. All rights reserved. X * X * X * Synopsis: X * holidays [flags] [ year] X * X * For flags see usage printf below. X * If no year is specified then the current year is printed. X * If a year is specified then a holiday calendar for that year is printed. X * X *********************************************************************/ X X#include <stdio.h> X#include <sys/types.h> X#include <time.h> X#include "taxc.h" X X#define DAY (24L*3600L) X#define SIDEREAL_MO ((long) (29.5306*DAY)) X#define FIRST_Q ((long) ((29.5306*DAY)/4L)) X#define FULL ((long) ((29.5306*DAY)/2L)) X#define LAST_Q ((long) ((29.5306*3L*DAY)/4L)) X#define HALF_DAY (DAY/2L) X#define D(m,w,d) ((m)*100+(w)*10+(d)) X X X/********************************************************************* X * X * Miscellaneous GLOBAL Values: X * X *********************************************************************/ X Xchar *usage[] = { "usage: %s [flags] [year]", X " Calendar Content (Default: -h)", X " -h Holidays only printed", X " -a All, one line for each day of year", X " -u Print this usage statement", X " Annotation Content (Default: -beLp1)", X " -b Both religious and secular calendar", X " -B Neither religious nor secular calendar", X " -r Religious feasts", X " -s Secular holidays and memoria", X " -e Historical events", X " -p <0-9> Priority limit on annotation", X " -l Lunar phases", X " Date Format (Default: -NwmdF)", X " -n Day number of year", X " -w Week day", X " -m Month name", X " -d Day of month", X " -t Two digit year", X " -f Four digit year", X " -z todo file format", X "Capital letters reverse meaning of entry", X "If year is not specified the current year is used.", X NULLS }; X Xtypedef struct { int w1, w2, w3, w4; char *desc; } hday; X X X/* Events in History Based on Fixed Days in a Particular Year */ X X Xhday events[] = X /* start end day pri string to print */ X { { 1939, 1939, -1, 0, "Start of WW II" }, /* */ X { 1945, 1945, 132, 0, "V-E Day" }, /* May 13th */ X { 1915, 1915, 127, 0, "Sinking of the Lusitania" }, /* May 7th */ X { 1914, 1914, 178, 0, "Start of WW I" }, /* Jun 28th */ X { 1919, 1919, 178, 0, "Treaty of Versailles" }, /* Jun 28th */ X { 1945, 1945, 225, 0, "V-J Day" }, /* Aug 14th */ X { 1929, 1929, 296, 0, "Wall Steet Panic" }, /* Oct 24th */ X { 1941, 1941, 325, 0, "Pearl Harbor" }, /* Nov 22nd */ X { 1968, 1968, 325, 0, "JFK Assassinated" }, /* Nov 22th */ X { -1, -2, 366, 10, NULLS } }; X X X/* Holidays in Secular Calendar Based on Fixed Days */ X Xhday secular[] = X /* start end day pri string to print */ X { { 1896, 0, 32, 4, "Ground Hog Day" }, /* Feb 2th */ X { 1896, 0, 42, 2, "Lincoln's Day (US)" }, /* Feb 12th */ X { 1755, 0, 52, 2, "Washington's Day (US)" }, /* Feb 22th */ X { 0, 0, 90, 3, "April Fool's Day" }, /* Apr 1st */ X { 1890, 0, 103, 3, "Pan American Day" }, /* Apr 14th */ X { 0, 0, 120, 3, "May Day / Labor Day" }, /* May 1st */ X { 1853,/*?*/0, 124, 4, "Independence Day (Mexico)" }, /* May 5th */ X { 1819, 0, 144, 3, "National Maritime Day" }, /* May 22th */ X { 1880, 0, 146, 4, "British Empire Day" }, /* May 24th */ X { 1866, 1940, 149, 3, "Decoration Day (US)" }, /* May 30th */ X { 1941, 1976, 149, 3, "Memorial Day (US)" }, /* May 30th */ X { 1789, 0, 164, 3, "Flag Day (US)" }, /* Jun 14th */ X { 0, 0, 181, 4, "Canada Day" }, /* July 1th */ X { 1776, 0, 184, 1, "Independence Day (US)" }, /* Jul 4th */ X { 1778, 0, 194, 4, "Bastille Day" }, /* Jul 14th */ X { 1850, 0, 246, 5, "Los Angeles Day" }, /* Sep 4th */ X { 1854, 0, 251, 4, "California Admission Day" }, /* Sep 9th */ X { 1779, 1951, 256, 3, "Constitution Day (US)" }, /* Sep 14th */ X { 1952, 0, 259, 3, "Citizenship Day" }, /* Sep 17th */ X { 1940, 0, 271, 9, "Buz' Day" }, /* Sep 29th */ X { 1493, 1978, 284, 2, "Columbus Day (US)" }, /* Oct 12th */ X { 1945, 0, 296, 2, "United Nations Day" }, /* Oct 24th */ X { 1920, 0, 314, 2, "Veteran's Day" }, /* Nov 11th */ X { 1803, 0, 308, 3, "Guy Fawkes' Day" }, /* Nov 5th */ X { 1941, 0, 348, 5, "Bill of Rights Day" }, /* Dec 15th */ X { 1903, 0, 350, 5, "Wright Bros. Day" }, /* Dec 17th */ X { 0, 0, 359, 5, "Boxing Day" }, /* Dec 26th */ X { -1, -2, 366, 10, NULLS } }; X X X X/* Holidays in Christian Calendar Based on Fixed Days */ X Xhday reldays[] = X /* start end day pri string to print */ X { { 0, 0, 5, 3, "Epiphany" }, /* Jan 6th */ X { 0, 0, 32, 3, "Candelmas" }, /* Feb 2nd */ X { 0, 0, 83, 4, "Mary's Annunciation" }, /* Mar 25th */ X { 0, 0, 179, 4, "Saint Peter's Day" }, /* Jun 29th */ X { 0, 0, 180, 4, "Saint Paul's Day" }, /* Jun 30th */ X { 0, 0, 217, 3, "Feast of the Transfiguration" },/* Aug 6th */ X { 0, 0, 226, 4, "Mary's Assumption" }, /* Aug 15th */ X { 0, 0, 250, 4, "Mary's Nativity" }, /* Sep 8th */ X { 0, 0, 256, 5, "Exaltation of the Cross" }, /* Sep 14th */ X { 0, 0, 271, 4, "Michaelmas" }, /* Sep 29th */ X { 0, 0, 304, 4, "All Martyr's Day" }, /* Nov 1st */ X { 0, 0, 330, 2, "(Advent Begins)" }, /* Nov 27th */ X { -1, -2, 366, 10, NULLS } }; X X/* Holidays in Christian Calendar based on Easter Sunday */ X Xhday eastdays[] = X /* start end day pri string to print */ X { { 0, 0, -56, 2, "Septuagesima" }, /* 70 days before Easter? */ X { 0, 0, -49, 2, "Sexagesima" }, /* 60 days before Easter? */ X { 0, 0, -50, 3, "(Carnival Begins)" }, X { 0, 0, -42, 2, "Quinquagesima" },/* 50 days before Easter? */ X { 0, 0, -40, 3, "Shrove Tuesday (Carnival Ends)" }, X /* { 0, 0, -40, 3, "Mardi Gras Day (Carnival Ends)" }, /* Alt */ X { 0, 0, -39, 1, "Ash Wednesday" },/* 40 days before Easter */ X { 0, 0, -7, 0, "Palm Sunday" }, /* 10 days before Easter? */ X { 0, 0, -3, 2, "Maundy Thursday" }, X { 0, 0, -2, 1, "Good Friday" }, X /* { 0, 0, 0, 0, "Easter Sunday" },/* Handled directly in pgm*/ X /* 40 days after Easter */ X { 0, 0, 39, 3, "Holy Thursday (Feast of the Ascension)" }, X /* 50 days after Easter */ X { 0, 0, 49, 0, "Pentecost (Whitsunday)" }, X /* 60 days after Easter? */ X { 0, 0, 56, 1, "Trinity Sunday" }, X { -1, -2, 366, 10, NULLS } }; X X/* Holidays in Both Christian and Secular Calendars Based on Fixed Days */ X Xhday bothdays[] = X /* start end day pri string to print */ X { { 0, 0, 0, 0, "New Year's Day" }, /* Jan 1st */ X /* { 1983, -1, 14, 2, "Martin Luther King Jr Day" }, /* Jan 15th */ X { 1974, 1974, 5, 0, "Daylight Savings Begins" }, /* Jan 6th */ X { 1942, 1942, 39, 0, "Daylight Wartime Begins" }, /* Feb 9th */ X { 0, 0, 44, 1, "Saint Valentines' Day" }, /* Feb 14th */ X { 1975, 1975, 53, 0, "Daylight Savings Begins" }, /* Feb ??th */ X { 0, 0, 73, 3, "Ides of March (Beware!!)" }, /* Mar 15th */ X { 0, 0, 75, 3, "Saint Patrick's Day" }, /* Mar 17th */ X { 0, 0, 79, 3, "Vernal Equinox" }, /* Mar 21st */ X /* { 1914, 0, 104, 0, "Ceasar's Rendering Day" }, /* Apr 15th */ X { 0, 0, 171, 3, "Summer Solistice" }, /* Jun 21st */ X { 0, 0, 246, 5, "Kid's Day" }, /* Sep 4th */ X { 0, 0, 263, 3, "Autumnal Equinox" }, /* Sep 21st */ X { 1942, 1942, 271, 0, "Standard Time Begins" }, /* Sep 30th */ X { 1918, 1919, 277, 0, "Standard Time Begins" }, /* Oct 5th */ X { 0, 0, 303, 0, "Halloween"}, /* Oct 31th */ X { 0, 0, 354, 3, "Winter Solistice" }, /* Dec 21st */ X { 0, 0, 357, 0, "Christmas Eve" }, /* Dec 24th */ X { 0, 0, 358, 0, "Christmas" }, /* Dec 25th */ X { 0, 0, 364, 0, "New Year's Eve" }, /* Dec 31st */ X { -1, -2, 366, 10, NULLS } }; X X X/* Holidays in Both Christian and Secular Calendars Based on Weekday */ X Xhday daydays[] = X /* month * 100 */ X /* + wkinx * 10 */ X /* start end + wday pri string to print */ X { { 1967, 0, 10, 1, "Superbowl Sunday" }, /* 2nd Sun Jan */ X { 1983, 0, 21, 1, "Martin Luther King Jr Day" },/* 3rd Mon Jan */ X /* { 1960, 0, 250, 0, "Daylight Savings (Europe)" },/* LastSun Mar */ X { 1918, 1919, 250, 0, "Daylight Wartime" }, /* LastSun Mar */ X { 1967, 1973, 350, 0, "Daylight Savings" }, /* LastSun Apr */ X { 1976, 1986, 350, 0, "Daylight Savings" }, /* LastSun Apr */ X /* 1st Sun Apr */ X { 1987, 0, 300, 0, "Daylight Savings (Spring Forward)" }, X { 1911, 0, 410, 0, "Mother's Day" }, /* 2nd Sun May */ X { 0, 0, 520, 0, "Father's Day" }, /* 3rd Sun Jun */ X { 1882, 0, 801, 0, "Labor Day" }, /* 1st Mon Sep */ X /* { 1960, 0, 850, 0, "Standard Time (Europe)" }, /* LastSun Sep */ X { 1967, 0, 950, 0, "Standard Time (Fall Back)" },/* LastSun Oct */ X { 0, 0, 1033, 0, "Thanksgiving Day (US)" }, /* 4th Thu Nov */ X { -1, -2, 1268, 10, NULLS } }; X X X X X/* Holidays in Secular Calendar Based on Weekday */ X Xhday dscdays[] = X /* month * 100 */ X /* + wkinx * 10 */ X /* start end + wday pri string to print */ X { { 1975, 0, 131, 1, "President's Day" }, /* 3rd Mon Feb */ X { 1950, 0, 426, 3, "Armed Forces' Day (US)" }, /* 3rd Sat May */ X { 1940, 1951, 420, 3, "I'm an American Day" }, /* 3rd Sun May */ X { 1977, 0, 451, 3, "Memorial Day" }, /* LastMon May */ X { 1865, 0, 510, 3, "Children's Day" }, /* 2nd Sun Jun */ X { 1979, 0, 810, 0, "Grandparent's Day" }, /* 2nd Sun Sep */ X { 1979, 0, 901, 2, "Child Health Day" }, /* 1st Mon Oct */ X { 1979, 0, 911, 2, "Columbus Day (Obs-US)" }, /* 2nd Mon Oct */ X { 1863, 0, 911, 4, "Thanksgiving Day (Canada)" },/* 2nd Mon Oct */ X { -1, -2, 1268, 10, NULLS } }; X X X X X X X X X X X X X X X X X Xchar *mon_name[] ={" Jan", " Feb", " Mar", " Apr", " May", " Jun", X " Jul", " Aug", " Sep", " Oct", " Nov", " Dec" }; Xint mon_days[] ={ 31, 28, 31, 30, 31, 30, X 31, 31, 30, 31, 30, 31 }; Xchar *day_name[] ={" Sun", " Mon", " Tue", " Wed", " Thu", " Fri", " Sat"}; X X Xchar *myname; /* How program was invoked */ X Xint yrday(); Xint weeknum(); Xint daynum(); Xlong uxeaster(); Xlong uxdate(); Xlong uxtime(); Xvoid datex(); X X X/************************************************************************ X * X * Holidays -- Print a holiday calendar for a given year. X * X ************************************************************************/ X Xint PROC main (argc, argv) X int argc; X char **argv; X X{ int y; X long time(); X char j; X struct tm *localtime(), *gmtime(), *tp; X int ds, ids, syd, ly, i, nday, wi, di, cy, cm, cyd, cmd, cwd; X int ep, sp, bp, dp, rp, cp; /* pointers into the annotation arrays */ X int e_month; X long daysold, lbase, now, nd, cd; X#ifdef EBUG X int nfd; X long ncd; X#endif X Bool lwdm = FALSE; X long e_s; X int e_sun; X char dateline[80], info[80]; X int mnum, mnum2; /* Magic numbers for checking days */ X int pri = 1; /* Priority of Holiday (important) */ X Bool sechf = TRUE; /* Print secular holidays */ X Bool relhf = TRUE; /* Print religious holidays */ X Bool eventf = TRUE; /* Print history events */ X Bool holf; /* True if any holidays printed */ X Bool alldaysf = FALSE; /* Print every day in year */ X Bool daynumf = FALSE; /* Print day number of day in year */ X Bool wdayf = TRUE; /* Print week day of date */ X Bool monthf = TRUE; /* Print month of date */ X Bool mdayf = TRUE; /* Print month day of date */ X Bool syrf = FALSE; /* Print year in 2 digit format */ X Bool lyrf = FALSE; /* Print year in 4 digit format */ X Bool moif = FALSE; /* Print week day index in month */ X Bool nyrf; /* True if no year to be printed */ X Bool lunarf = FALSE; /* Print moon in quarter phases */ X Bool seasonf = FALSE; /* Print start of seasons */ X Bool todof = FALSE; /* Print todo file format */ X X extern int optind; /* from getopt() */ X extern char *optarg; /* from getopt() */ X int option; /* option "letter" */ X char *type; /* Religious or Holiday */ X X X/********************************************************************* X * X * Process Arguments X * X *********************************************************************/ X X myname = *argv; X X optind = 1; X while ((option = getopt (argc, argv, "ABCDEFHILMNRSTWZabcdefhilmnp:rstwz")) != EOF) X { switch (option) X { case 'a': alldaysf = TRUE; break; /* All days printed */ X case 'A': alldaysf = FALSE; break; /* Only Holidays printed*/ X case 'b': relhf = TRUE; /* both relig & secular Hol*/ X eventf = TRUE; X sechf = TRUE; break; X case 'B': relhf = FALSE; /* neither rel | secu Hol*/ X eventf = FALSE; X sechf = FALSE; break; X case 'd': mdayf = FALSE; break; /* Day of month */ X case 'D': mdayf = FALSE; break; /* Day of month deleted */ X case 'e': eventf = TRUE; break; /* Historical events prt */ X case 'E': eventf = FALSE; break; /* Historical events del */ X case 'f': lyrf = TRUE; break; /* Four digit year printed */ X case 'F': lyrf = FALSE; /* No year printed */ X syrf = FALSE; break; X case 'h': alldaysf = FALSE; break; /* Only holidays printed */ X case 'H': alldaysf = TRUE; break; /* All days Printed */ X case 'i': moif = TRUE; break; /* Week and Day indexes */ X case 'I': moif = FALSE; break; /* No Week and Day indexes */ X case 'l': lunarf = TRUE; break; /* Phases of the moon */ X case 'L': lunarf = FALSE; break; /* No Phases of the moon */ X case 'm': monthf = TRUE; break; /* Month name printed */ X case 'M': monthf = FALSE; break; /* Month name deleted */ X case 'n': daynumf = TRUE; break; /* Day of year printed */ X case 'N': daynumf = FALSE; break; /* Day of year deleted */ X case 'p': pri = atoi(optarg); break; /* Prio of Holiday */ X case 'c': /* Christian festivals prt */ X case 'r': relhf = TRUE; break; /* Religious festivals prt */ X case 'C': /* Christian festivals del */ X case 'R': relhf = FALSE; break; /* Religious festivals del */ X case 's': sechf = TRUE; break; /* Secular holidays printed*/ X case 'S': sechf = FALSE; break; /* Secular holidays deleted*/ X case 't': syrf = TRUE; break; /* Two digit years */ X case 'T': lyrf = FALSE; /* No year printed */ X syrf = FALSE; break; X case 'w': wdayf = TRUE; break; /* Week day printed */ X case 'W': wdayf = FALSE; break; /* Week day deleted */ X case 'z': todof = TRUE; break; /* Date in to do format */ X case 'Z': todof = FALSE; break; /* Date in to do format */ X default: Usage(); } /* Usage message */ X } X X argc -= optind; /* skip options */ X argv += optind; X X now = time( (long *)0 ); X tp = localtime( &now ); X y = tp->tm_year + 1900; X X if ( argc == 1 ) X then sscanf ( argv[0], " %d%c", &y, &j ); X X if ( y < 1913 || y > 2037 ) X then X { printf ( "Unix calendar out of range. Calendar undefined.\n" ); X return ( 0 ); } X X X X/********************************************************************* X * X * Initial Setup X * X *********************************************************************/ X X cd = uxdate ( y, 1, 1); X e_s = uxeaster ( y ); /* Get what day easter is */ X X if ( lunarf ) X then X { lbase = uxdate( 1979, 2, 26 ); /* Date and time of new moon */ X lbase += uxtime( 16, 0, 0 ); } X X if (relhf && sechf) X then type = "Christian and Holiday"; X else if ( relhf) X then type = "Christian's"; X else type = "Holiday"; X e_sun = (e_s - cd) / DAY; /* Get what day easter is */ X printf ("\nA %s Calendar for Year %d\n\n", type, y); X X ly = leap(y); X if ( ly ) X then nd = 366; X else nd = 365; X X if (relhf || sechf || lunarf || eventf ) X then holf = TRUE; X else holf = FALSE; X X if ( syrf || lyrf ) X then nyrf = FALSE; X else nyrf = TRUE; X X X X/********************************************************************* X * X * Loop Through Days in Year X * X *********************************************************************/ X X ep = sp = bp = dp = rp = cp = 0; X X for (nday=0; nday<nd; nday++) X { /* Get current date info out of datelib */ X X datex( cd, &cy, &cm, &cyd, &cmd, &cwd ); X X#ifdef EBUG X /* Check year */ X if ( cy != y ) X then X { printf ("year check failed: y = %d, cy = %d\n", y, cy); X printf (" cm = %d, cyd = %d, cmd = %d, cwd =%d\n", X cm, cyd, cmd, cwd); } X X /* Reverse Engineer the Unix date */ X ncd = uxdate( cy, cm+1, cmd+1 ); X if ( cd != ncd ) X then printf ("uxdate check failed: cd = %ld, ncd = %ld\n", cd, ncd); X X /* Reverse Engineer the Number of Full Days Sofar this Year */ X nfd = yrday( cy, cm+1, cmd+1 ); X if ( cyd != nfd || cyd != nday) X then printf ("yrday check failed: nday = %d, cyd = %d, nfd = %d\n", X nday, cyd, nfd); X#endif X X wi = weeknum( cd ); X di = daynum ( cd ); X X X/********************************************************************* X * X * Format Date X * X *********************************************************************/ X X dateline[0] = NULLC; X if ( todof ) X then /* >Sat Jun 6 87 +! */ X sprintf ( dateline, ">%s%s %2d %2d +!", X day_name[cwd]+1, mon_name[cm], cmd+1, cy-1900 ); X else X { if ( daynumf ) X then (sprintf( info, "%3d", nday+1 ), strcat ( dateline, info )); X if ( wdayf ) X then ( strcat ( dateline, day_name[cwd] )); X if ( monthf ) X then (strcat ( dateline, mon_name[cm] )); X if ( mdayf ) X then (sprintf( info, " %2d", cmd+1 ), strcat ( dateline, info )); X if ( syrf ) X then (sprintf( info, " %2d ", cy-1900 ), strcat ( dateline, info )); X if ( lyrf ) X then (sprintf( info, ", %4d ", cy ), strcat ( dateline, info )); X if ( nyrf ) X then (strcat ( dateline, " " )); X if ( moif ) X then (sprintf( info, "[%d-%d] ", wi,di), strcat ( dateline, info )); X } X X if ( !lunarf ) strcat ( dateline, " " ); X X if ( cyd == 0 ) /* ds is a count characters in the date string */ X then ids = strlen( dateline ) + (lunarf ? 5 : 0); X X ds = ids; X X syd = (ly&&cyd>60) ? cyd-1 : cyd; /* Create a standard date */ X X e_month = (cm == 1 && ly) ? mon_days[cm]+1 : mon_days[cm]; X X lwdm = ((cmd+9)>e_month) ? TRUE : FALSE; /* 7 + 1 for cmd + 1 to pass */ X X /* Todays magic numbers: -1 is not equal to anything else */ X mnum = cm*100+di*10+cwd; /* any other weekday */ X mnum2 = ( lwdm ? (cm*100+50+cwd) : -1); /* last weekday of mo */ X X X X/********************************************************************* X * X * Annotate Date with Holidays X * X *********************************************************************/ X X if ( holf ) X then /* Mark Holidays */ X X /* ANNOTATE WITH LUNAR AND SEASONAL EVENTS */ X X { if ( lunarf ) X then X { if ( lbase < cd ) X then daysold = (cd - lbase) % SIDEREAL_MO; X else daysold = SIDEREAL_MO - ((lbase - cd) % SIDEREAL_MO); X X /**/ if ( (daysold > (FIRST_Q - HALF_DAY)) && X (daysold < (FIRST_Q + HALF_DAY)) ) X then strcat( dateline, " |) "); X X else if ( (daysold > FULL - HALF_DAY) && X (daysold < FULL + HALF_DAY) ) X then strcat( dateline, " () "); X X else if ( (daysold > (LAST_Q - HALF_DAY)) && X (daysold < (LAST_Q + HALF_DAY)) ) X then strcat( dateline, " (| "); X X else if ( (daysold > SIDEREAL_MO-HALF_DAY) || X (daysold < HALF_DAY) ) X then strcat( dateline, " [] "); X else strcat( dateline, " "); } X X X /* ANNOTATE WITH GENERAL INFORMATION */ X X if ( eventf ) /* Mark Events */ X then X { X for ( ; events[ep].w1 >= 0; ep++ ) X { if ( events[ep].w3 > syd ) X then goto secstuff; X else if ( ( events[ep].w1 <= cy && X events[ep].w2 >= cy && X events[ep].w3 == syd ) || X ( events[ep].w1 <= cy && X events[ep].w2 == 0 && X events[ep].w3 == syd ) || X ( events[ep].w1 == 0 && X events[ep].w3 == syd ) ) X then if (events[ep].w4 <= pri) X then X { strcat( dateline, events[ep].desc ); X strcat( dateline, " " ); X goto secstuff; } X } X X } X X X /* ANNOTATE WITH SECULAR INFORMATION */ X X secstuff: X if ( sechf ) /* Mark Secular Holidays */ X then X { X for ( ; secular[sp].w1 >= 0; sp++ ) X { if ( secular[sp].w3 > syd ) X then goto wdays; X else if ( ( secular[sp].w1 == 0 && X secular[sp].w3 == syd ) || X ( secular[sp].w1 <= cy && X secular[sp].w2 == 0 && X secular[sp].w3 == syd ) || X ( secular[sp].w1 <= cy && X secular[sp].w2 >= cy && X secular[sp].w3 == syd ) ) X then if (secular[sp].w4 <= pri) X then X { strcat( dateline, secular[sp].desc ); X strcat( dateline, " " ); X goto wdays; } X } X X wdays: X X /* Check for Holidays Days based on Weekday */ X X for ( dp=0; dscdays[dp].w1 != -1; dp++ ) X if ( ( dscdays[dp].w1 == 0 && /* no date restrict */ X (dscdays[dp].w3 == mnum || X dscdays[dp].w3 == mnum2 )) || X ( dscdays[dp].w1 <= cy && /* no ending date */ X dscdays[dp].w2 == 0 && X (dscdays[dp].w3 == mnum || X dscdays[dp].w3 == mnum2 )) || X ( dscdays[dp].w1 <= cy && /* both yrs present */ X dscdays[dp].w2 >= cy && X (dscdays[dp].w3 == mnum || X dscdays[dp].w3 == mnum2 ))) X then if (dscdays[dp].w4 <= pri) X then X { strcat( dateline, dscdays[dp].desc ); X strcat( dateline, " " ); } X X /* Special Cases: Victoria Day, Easter Monday, Sadie Hawkin's Day */ X X if ( cm == 4 && cwd == 1 && cmd<25 && cmd>18 ) /* Victoria Day */ X then if ( 4 <= pri ) X then strcat( dateline, "Victoria Day (Canada) " ); X X if ( cyd == e_sun+1 ) /* Easter Monday */ X then if ( 4 <= pri ) X then strcat( dateline, "Easter Monday (Canada) " ); X X if ( cm == 10 && cwd == 0 && cmd>11 && cmd<18 ) X then if ( 4 <= pri ) X then strcat( dateline, "Sadie Hawkin's Day " ); X X } X X X /* ANNOTATE WITH IMPORTANT HOLIDAYS TO BOTH CALENDARS */ X X if ( sechf || relhf ) /* Mark Important Holidays */ X then X { X /* Check for Fixed Secular Holidays in both Calendars */ X X for ( ; bothdays[bp].w1 >= 0; bp++ ) X { if ( bothdays[bp].w3 > syd ) X then goto bigdays; X else if ( ( bothdays[bp].w1 == 0 && /* no dates */ X bothdays[bp].w3 == syd ) || X ( bothdays[bp].w1 <= cy && /* no end date */ X bothdays[bp].w2 == 0 && X bothdays[bp].w3 == syd ) || X ( bothdays[bp].w1 <= cy && /* date limits */ X bothdays[bp].w2 >= cy && X bothdays[bp].w3 == syd ) ) X then if (bothdays[bp].w4 <= pri) X then X { strcat( dateline, bothdays[bp].desc ); X strcat( dateline, " " ); X goto bigdays; } X } X X X bigdays: X X /* Check for Holidays Days based on Weekday */ X X for ( dp=0; daydays[dp].w1 != -1; dp++ ) X if ( ( daydays[dp].w1 == 0 && /* no date restrict */ X (daydays[dp].w3 == mnum || X daydays[dp].w3 == mnum2 )) || X ( daydays[dp].w1 <= cy && /* no ending date */ X daydays[dp].w2 == 0 && X (daydays[dp].w3 == mnum || X daydays[dp].w3 == mnum2 )) || X ( daydays[dp].w1 <= cy && /* both yrs present */ X daydays[dp].w2 >= cy && X (daydays[dp].w3 == mnum || X daydays[dp].w3 == mnum2 ))) X then if (daydays[dp].w4 <= pri) X then X { strcat( dateline, daydays[dp].desc ); X strcat( dateline, " " ); } X X /* Special_cases: Election Day and Easter */ X X /* First Tue in Nov excep if Tue the 1st */ X /**/ if ( cm == 10 && cwd == 2 && di == 0 && cmd != 0) X then strcat( dateline, "Election Day (US) " ); X X else if ( cm == 10 && cwd == 2 && cmd == 7) /* else Nov 8th */ X then strcat( dateline, "Election Day (US) " ); X X if ( cyd == e_sun ) /* Easter Sunday */ X then strcat( dateline, "Easter Sunday " ); X X if ( syd == 104 ) /* April 15th */ X then if ( relhf ) X then strcat( dateline, "Ceasar's Rendering Day " ); X else strcat( dateline, "IRS' Day (US) " ); X X } /* End of Secular Holidays Important to Both Calendars */ X X X /* ANNOTATE WITH CHRISTIAN HOLIDAYS */ X X if ( relhf ) X then X { for ( ; reldays[rp].w1 >= 0; rp++ ) X { if ( reldays[rp].w3 > syd ) X then goto east; X else if ( ( reldays[rp].w1 == 0 && X reldays[rp].w3 == syd ) || X ( reldays[rp].w1 <= cy && X reldays[rp].w2 == 0 && X reldays[rp].w3 == syd ) || X ( reldays[rp].w1 <= cy && X reldays[rp].w2 >= cy && X reldays[rp].w3 == syd ) ) X then if (reldays[rp].w4 <= pri) X then X { strcat( dateline, reldays[rp].desc ); X strcat( dateline, " " ); X goto east; } X } X X /* ANNOTATE WITH FLOATING CHRISTIAN HOLIDAYS */ X X east: X X /* Check for Feast days based on Easter */ X X for ( ; eastdays[cp].w1 >= 0; cp++ ) X { if ( eastdays[cp].w3 > (cyd - e_sun) ) X then goto printit; X else if ( ( eastdays[cp].w1 == 0 && X eastdays[cp].w3 == (cyd - e_sun) ) || X ( eastdays[cp].w1 <= cy && X eastdays[cp].w2 == 0 && X eastdays[cp].w3 == (cyd - e_sun) ) || X ( eastdays[cp].w1 <= cy && X eastdays[cp].w2 >= cy && X eastdays[cp].w3 == (cyd - e_sun) ) ) X then if (eastdays[cp].w4 <= pri) X then X { strcat( dateline, eastdays[cp].desc ); X goto printit; } X } X X } /* End of Christian Festivals */ X X } /* End of Holidays */ X X X X X X/********************************************************************* X * X * Print Date and Annotations if Interesting X * X *********************************************************************/ X X printit: X X /* Trim blanks off the end of the line */ X X for ( i=strlen(dateline)-1; ((dateline[i]==' ')&&(i>0)); i-- ); X if (i > 0) then dateline[i+1] = NULLC; X X if ( alldaysf || /* all days to be printed */ X (strlen(dateline) > ids) || /* Holiday info on line */ X (lunarf && dateline[ids-3] != ' ') ) /* A lunar event */ X then printf( "%s\n", dateline ); X X X X /* Advance yet another day */ X cd += DAY; X } X X X/********************************************************************* X * X * Finish up: X * X *********************************************************************/ X X return (0); X X} /* test of datelib */ X X X X X X X/************************************************************************ X * X * USAGE X * X * Print usage messages (char *usage[]) to stderr and exit nonzero. X * Each message is followed by a newline. X * X ************************************************************************/ X XPROC Usage() X{ X register int which = 0; /* current line */ X X while (usage [which] != NULLS) X { fprintf (stderr, usage [which++], myname); X putc ('\n', stderr); X } X X exit (1); X X} /* Usage */ SHAR_EOF if test 30663 -ne "`wc -c < 'holidays.c'`" then echo shar: error transmitting "'holidays.c'" '(should have been 30663 characters)' fi fi # end of overwriting check # End of shell archive exit 0