[net.sources] sunrise/sunset, today, potm

jad@hpfcla.UUCP (jad) (08/10/85)

	This came from a request in net.astro for astronomical software.
	Read the discussion back there for more info on what this is and
	what mods you may have to make to it for it to run there.

/***** hpfclo:net.astro / jad /  3:15 pm  Aug  9, 1985*/

	Here is the shell archive of both sun and today.  I lumped them
	both together since they're under 50,000 bytes total.  Save this
	in a file somewhere, type "sh file", and POOF!, out pop two new
	directories, ready to make ... have fun!

				--	jad	 --
				John A. Dilley, FSD
				Fort Collins,    CO

ARPA:				terrapin@Purdue.EDU
UUCP:				{ihnp4}! hpfcla!jad
PHONE:				(303)226-3800 x4166

#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by jad at hpfclo on Wed Aug  7 15:46:20 1985
#
# This archive contains:
#	sun	today	
#
# File overwrite is not allowed.
#

echo mkdir - sun
mkdir sun

if test -f sun/Makefile
then
    echo shar: sun/Makefile already exists.  Stop!
    exit 1
fi
echo x - sun/Makefile
cat >sun/Makefile <<'@EOF'
# Makefile for sun(1) program.
HOME=/users/sun3/jad
BINDIR=${HOME}/bin

sun:	sun.c
	cc -s -O -o sun sun.c -lm
    
manual:	sun.1
	nroff -man sun.1 > sun.1.out

install:	sun
	mv sun ${BINDIR}

clean:
	-rm -f sun a.out core ERRS ,* *.o
@EOF

chmod 644 sun/Makefile

if test -f sun/Fbob
then
    echo shar: sun/Fbob already exists.  Stop!
    exit 1
fi
echo x - sun/Fbob
sed 's/^@//' >sun/Fbob <<'@EOF'
@From uucp Tue May 28 16:52:15 1985
>From tektronix!reed!nsc-pdc!rgb  Tue May 28 17:19:23 1985 remote from ihnp4
@From: ihnp4!tektronix!reed!nsc-pdc!rgb
Received: by ihnp4.ATT.UUCP id AA01966; 28 May 85 17:19:23 CDT (Tue)
To: reed!tektronix!ihnp4!hpfcla!ajs
Received: from reed.uucp by tektronix ; 28 May 85 15:01:28 PDT
Received: by reed.UUCP (4.12/1.0),	id AA07764; Tue, 28 May 85 14:56:55 pdt
Received: by nsc-pdc.UUCP (4.12/4.7),	id AA27797; Tue, 28 May 85 09:08:58 pdt
Date: Tue, 28 May 85 09:08:58 pdt
Message-Id: <8505281608.AA27797@nsc-pdc.UUCP>
Subject: Re:  sun(1)
Status: R

Alan, 

The best book I have seen to date is a small book called "Practical
Astronomy With Your Calculator" by Peter(?) Duffet-Smith.  I was able
to order a copy from a local bookstore.  The B. Dalton here said they
stock it, but they happened to have sold them all.

As far as the definition of sunset, there are lots of them. The program
uses the time when the upper limb of the sun descends below the horizon.
Note that it is calculated for the observer; a more accurate calculation
would include your mountains. Refraction causes a sun which is already
below the horizon to appear to be above.  

					Bob Bond


@EOF

chmod 644 sun/Fbob

if test -f sun/Fbob\:sun
then
    echo shar: sun/Fbob\:sun already exists.  Stop!
    exit 1
fi
echo x - sun/Fbob\:sun
sed 's/^@//' >sun/Fbob\:sun <<'@EOF'
@From uucp Fri May 24 22:30:40 1985
>From tektronix!reed!nsc-pdc!rgb  Fri May 24 20:02:13 1985 remote from ihnp4
@From: ihnp4!tektronix!reed!nsc-pdc!rgb
Received: by ihnp4.ATT.UUCP id AA24414; 24 May 85 20:02:13 CDT (Fri)
To: reed!tektronix!ihnp4!hpfcla!ajs
Received: from reed.uucp by tektronix ; 24 May 85 13:04:13 PDT
Received: by reed.UUCP (4.12/1.0),	id AA21666; Fri, 24 May 85 13:00:54 pdt
Received: by nsc-pdc.UUCP (4.12/4.7),	id AA19161; Fri, 24 May 85 11:14:20 pdt
Date: Fri, 24 May 85 11:14:20 pdt
Message-Id: <8505241814.AA19161@nsc-pdc.UUCP>
Subject: Re:  sun(1)
Status: R

The program calculates some corrections for sunset and sunrise positions
based on the refraction of the air, parallax, and one other thing I
forget now.  The postion figures don't do the correction: I wimped out
because the refraction correction is a function of the height of the
sun above the horizon.  The sunrise and sunset are apparent times, 
you should remove the dt correction to find the "astronomical" times.
Try the first day of spring at dawn to see what I mean.  The sun should
come up almost exactly in the east, but it's apparent position is
different because of the corrections.

I hope this is understandable...

						Bob

@EOF

chmod 644 sun/Fbob\:sun

if test -f sun/ideas
then
    echo shar: sun/ideas already exists.  Stop!
    exit 1
fi
echo x - sun/ideas
cat >sun/ideas <<'@EOF'
* Each option yields one type of output line, more or less.
* Set time in a variety of ways, including just hour or hour:min.
* Ditto for date.
* Option to get current or specified time included.
* Option to get just current position.
* Option to get time since/until previous/next sunrise/set, and percent of
  interval elapsed/remaining.
* Option to get length of day/night and percents.
* Work with standard TZ information.

Input options:

-a	latitude
-o	longitude
-z	timezone
[date and time] only argument allowed, various formats

Output options, sample:

-P	Latitude, longitude:	 40.02N 105.43W
-d	Date, time:		850419	 10:33	(MDT)
-t(def)	Rise, set times:	  5:33	 20:19  (MDT)
-a	Rise, set azimuth:	 61 19'	298 51'
-p	Current elev, azimuth:	 38 14'	180 00'
-s	Since-/till+ rise, set:	 -4:44	+10:02
-S	Since-/till+ rise, set:	-31.3%	+68.7%
-l	Length of night, day:	 14:10    9:50
-L	Length of night, day:	 60.2%   39.8%

-f	full, all of above
@EOF

chmod 444 sun/ideas

if test -f sun/sun.c
then
    echo shar: sun/sun.c already exists.  Stop!
    exit 1
fi
echo x - sun/sun.c
cat >sun/sun.c <<'@EOF'
/***** hpfcla:net.sources / nsc-pdc!rgb / 10:24 am  May 16, 1985
*
* Changed constants to Fort Collins, Colorado.  (ajs, 850520)
* Made other minor output format improvements also.
* 
*        sun <options>
*
*        options:        -t hh:mm:ss	time (default is current system time)
*			 -d mm/dd/yy	date (default is current system date)
*                        -a lat		decimal latitude (default = 45.5333)
*                        -o lon		decimal longitude (default = 122.8333) 
*			 -z tz		timezone (default = 8, pst)
*			 -p		show position of sun (azimuth)
*			 -v		turn on debugging
*        
*        All output is to standard io.  
*
*	 Compile with cc -O -o sun sun.c -lm
*	 Non 4.2 systems may have to change <sys/time.h> to <time.h> below.
*	(yes, done)
*
*	 Note that the latitude, longitude, time zone correction and
*	 time zone string are all defaulted in the global variable section.
*
*	 Most of the code in this program is adapted from algorithms
*	 presented in "Practical Astronomy With Your Calculator" by
*	 Peter Duffet-Smith.
*
*	 The GST and ALT-AZIMUTH algorithms are from Sky and Telescope,
*	 June, 1984 by Roger W. Sinnott
*
*	 Author Robert Bond - Beaverton Oregon.
*	
*/

#include <stdio.h>
#include <math.h>
#include <sys/types.h>
#include <time.h>

#define PI       3.141592654
#define EPOCH	 1980
#define JDE	 2444238.5	/* Julian date of EPOCH */

double dtor();
double adj360();
double adj24();
double julian_date();
double hms_to_dh();
double solar_lon();
double acos_deg();
double asin_deg();
double atan_q_deg();
double atan_deg();
double sin_deg();
double cos_deg();
double tan_deg();
double gmst();

int th;
int tm;
int ts;
int mo;
int day;
int yr;
int tz=7;			/* Default time zone */
char *tzs  = "(MST)";		/* Default time zone string */
char *dtzs = "(MDT)";		/* Default daylight savings time string */
int debug = 0;
int popt = 0;

double lat =  40.5253;		/* Default latitude (Fort Collins, Colorado) */
double lon = 105.0119;		/* Default Longitude (Degrees west) */ 

main(argc,argv)
int argc;
char *argv[];
{
    double ed, jd;
    double alpha1, delta1, alpha2, delta2, st1r, st1s, st2r, st2s;
    double a1r, a1s, a2r, a2s, dt, dh, x, y;
    double trise, tset, ar, as, alpha, delta, tri, da;
    double lambda1, lambda2;
    double alt, az, gst, m1;
    double hsm, ratio;
    time_t sec_1970;
    int h, m;
    struct tm *pt;

    sec_1970 = time((time_t *)0);  
    pt = localtime(&sec_1970);  

    th = pt->tm_hour;
    tm = pt->tm_min;
    ts = pt->tm_sec;
    yr = pt->tm_year + 1900;
    mo = pt->tm_mon + 1;
    day = pt->tm_mday;
    if (pt->tm_isdst) {		/* convert tz to daylight savings time */
	tz--;
	tzs = dtzs;	
    }

    initopts(argc,argv);

    if (debug)
        printf("Date: %d/%d/%d,  Time: %d:%d:%d, Tz: %d, Lat: %lf, Lon: %lf \n",
	    mo,day,yr,th,tm,ts,tz,lat,lon);

    jd = julian_date(mo,day,yr);
    ed = jd - JDE;

    lambda1 = solar_lon(ed);
    lambda2 = solar_lon(ed + 1.0);

    lon_to_eq(lambda1, &alpha1, &delta1);
    lon_to_eq(lambda2, &alpha2, &delta2);

    rise_set(alpha1, delta1, &st1r, &st1s, &a1r, &a1s);
    rise_set(alpha2, delta2, &st2r, &st2s, &a2r, &a2s);

    m1 = adj24(gmst(jd - 0.5, 0.5 + tz / 24.0) - lon / 15); /* lst midnight */

    if (debug)
	printf ("local sidereal time of midnight is %lf \n", m1);

    hsm = adj24(st1r - m1);

    if (debug)
	printf ("about %lf hours from midnight to dawn \n", hsm);

    ratio = hsm / 24.07;

    if (debug)
	printf("%lf is how far dawn is into the day \n", ratio);

    if (fabs(st2r - st1r) > 1.0) {
	st2r += 24.0;
	if (debug)
	    printf("st2r corrected from %lf to %lf \n", st2r-24.0, st2r);
    }

    trise = adj24((1.0 - ratio) * st1r + ratio * st2r);

    hsm = adj24(st1s - m1);

    if (debug)
	printf ("about %lf hours from midnight to sunset \n", hsm);

    ratio = hsm / 24.07;

    if (debug)
	printf("%lf is how far sunset is into the day \n", ratio);

    if (fabs(st2s - st1s) > 1.0) {
	st2s += 24.0;
	if (debug)
	    printf("st2s corrected from %lf to %lf \n", st2s-24.0, st2s);
    }

    tset = adj24((1.0 - ratio) * st1s + ratio * st2s);

    if (debug)
	printf("Uncorrected rise = %lf, set = %lf \n", trise, tset);

    ar = a1r * 360.0 / (360.0 + a1r - a2r);
    as = a1s * 360.0 / (360.0 + a1s - a2s);

    delta = (delta1 + delta2) / 2.0;
    tri = acos_deg(sin_deg(lat)/cos_deg(delta));

    x = 0.835608;		/* correction for refraction, parallax, ? */
    y = asin_deg(sin_deg(x)/sin_deg(tri));
    da = asin_deg(tan_deg(x)/tan_deg(tri));
    dt = 240.0 * y / cos_deg(delta) / 3600;

    if (debug)
	printf("Corrections: dt = %lf, da = %lf \n", dt, da);

    lst_to_hm(trise - dt, jd, &h, &m);
    printf("Sunrise: %2d:%02d\t\t", h, m);

    if (popt) {
        dh_to_hm(ar - da, &h, &m);
        printf("Azimuth: %3d %02d'\n", h, m);
    }

    lst_to_hm(tset + dt, jd, &h, &m);
    printf("Sunset:  %2d:%02d   ", h, m);

    if (popt) {
        dh_to_hm(as + da, &h, &m);
        printf("Azimuth: %3d %02d'\n", h, m);
    } else 
        printf("%s\n",tzs);

    if (popt) {

	if (alpha1 < alpha2)
	    alpha = (alpha1 + alpha2) / 2.0;
	else
	    alpha = (alpha1 + 24.0 + alpha2) / 2.0;
	
	if (alpha > 24.0)
	    alpha -= 24.0;

	dh = (hms_to_dh(th, tm, ts) + tz) / 24.0;
	if (dh > 0.5) {
	    dh -= 0.5;
	    jd += 0.5;
	} else {
	    dh += 0.5;
	    jd -= 0.5;
	}

	gst = gmst(jd, dh);

	eq_to_altaz(alpha, delta, gst, &alt, &az);

	printf	 ("The sun is at:   ");
	dh_to_hm (az, &h, &m);
	printf	 ("Azimuth: %3d %02d'  ", h, m);
	dh_to_hm (alt, &h, &m);
	printf	 ("Altitude: %3d %02d'\n", h, m);
    }
}

double
dtor(deg)
double deg;
{
    return (deg * PI / 180.0);
}

double
rtod(deg)
double deg;
{
    return (deg * 180.0 / PI);
}


double 
adj360(deg)
double deg;
{
    while (deg < 0.0) 
	deg += 360.0;
    while (deg > 360.0)
	deg -= 360.0;
    return(deg);
}

double 
adj24(hrs)
double hrs;
{
    while (hrs < 0.0) 
	hrs += 24.0;
    while (hrs > 24.0)
	hrs -= 24.0;
    return(hrs);
}

initopts(argc,argv)
int argc;
char *argv[];
{
    int ai;
    char *ca;
    char *str;

    while (--argc) {
        if ((*++argv)[0] == '-') {
	    ca = *argv;
	    for(ai = 1; ca[ai] != '\0'; ai++)
                switch (ca[ai]) {
		case 'v':
		    debug++;
		    break;
		case 'p':
		    popt++;
		    break;
                case 'a':
                    str = *++argv;
		    if (sscanf(str, "%lf", &lat) != 1)
			usage();
                    argc--;
                    break;
                case 'o':
                    str = *++argv;
		    if (sscanf(str, "%lf", &lon) != 1)
			usage();
                    argc--;
                    break;
                case 'z':
                    str = *++argv;
		    if (sscanf(str, "%d", &tz) != 1)
			usage();
		    tzs = "   ";
                    argc--;
                    break;
                case 't':
                    str = *++argv;
		    if (sscanf(str, "%d:%d:%d", &th, &tm, &ts) != 3)
			usage();
                    argc--;
                    break;
                case 'd':
                    str = *++argv;
		    if (sscanf(str, "%d/%d/%d", &mo, &day, &yr) != 3)
			usage();
                    argc--;
                    break;
                default: usage();
                }
        } else usage();
    }
}

usage()
{
    printf("Usage: sun [-p] [-t h:m:s] [-d m/d/y] [-a lat] [-o lon] [-z tz]\n");
    exit(1);
}

double 
julian_date(m, d, y)
{
    long a, b;
    double jd;

    if (m == 1 || m == 2) {
	--y;
	m += 12;
    }
    if (y < 1583) {
	printf("Can't handle dates before 1583\n");
	exit(1);
    }
    a = y/100;
    b = 2 - a + a/4;
    b += (int)((double)y * 365.25);
    b += (int)(30.6001 * ((double)m + 1.0));
    jd = (double)d + (double)b + 1720994.5;

    if (debug) 
	printf("Julian date for %d/%d/%d is %lf \n", m, d, y, jd);

    return(jd);
}

double 
hms_to_dh(h, m, s)
{
    double rv;
    rv = h + m / 60.0 + s / 3600.0;

    if (debug)
	printf("For time %d:%d:%d frac hours are: %lf \n", h, m, s, rv);

    return rv;
}

double 
solar_lon(ed)
double ed;
{
    double n, m, e, ect, errt, v;

    n = 360.0 * ed / 365.2422;
    n = adj360(n);
    m = n + 278.83354 - 282.596403;
    m = adj360(m);
    m = dtor(m);
    e = m; ect = 0.016718;
    while ((errt = e - ect * sin(e) - m) > 0.0000001) 
        e = e - errt / (1 - ect * cos(e));
    v = 2 * atan(1.0168601 * tan(e/2));
    v = adj360(v * 180.0 / PI + 282.596403);

    if (debug)
	printf("Solar Longitude for %lf days is %lf \n", ed, v); 

    return(v);
}

double 
acos_deg(x)
double x;
{
    return rtod(acos(x));
}

double 
asin_deg(x)
double x;
{
    return rtod(asin(x));
}

double 
atan_q_deg(y,x)
double y,x;
{
    double rv;

    if (y == 0)
        rv = 0;
    else if (x == 0)
        rv = y>0 ? 90.0 : -90.0;
    else rv = atan_deg(y/x);

    if (x<0) return rv+180.0;
    if (y<0) return rv+360.0;
    return(rv);
}

double
atan_deg(x)
double x;
{
    return rtod(atan(x));
}

double 
sin_deg(x)
double x;
{
    return sin(dtor(x));
}

double 
cos_deg(x)
double x;
{
    return cos(dtor(x));
}

double 
tan_deg(x)
double x;
{
    return tan(dtor(x));
}

lon_to_eq(lambda, alpha, delta)
double lambda;
double *alpha;
double *delta;
{
    double tlam,epsilon;

    tlam = dtor(lambda);
    epsilon = dtor((double)23.441884);
    *alpha = atan_q_deg((sin(tlam))*cos(epsilon),cos(tlam)) / 15.0;
    *delta = asin_deg(sin(epsilon)*sin(tlam));

    if (debug)
	printf("Right ascension, declination for lon %lf is %lf, %lf \n",
	    lambda, *alpha, *delta);
}

rise_set(alpha, delta, lstr, lsts, ar, as)
double alpha, delta, *lstr, *lsts, *ar, *as;
{
    double tar;
    double h;

    tar = sin_deg(delta)/cos_deg(lat);
    if (tar < -1.0 || tar > 1.0) {
	printf("The object is circumpolar\n");
	exit (1);
    }
    *ar = acos_deg(tar);
    *as = 360.0 - *ar;

    h = acos_deg(-tan_deg(lat) * tan_deg(delta)) / 15.0;
    *lstr = 24.0 + alpha - h;
    if (*lstr > 24.0)
	*lstr -= 24.0;
    *lsts = alpha + h;
    if (*lsts > 24.0)
	*lsts -= 24.0;

    if (debug) {
	printf("For ra, decl. of %lf, %lf: \n", alpha, delta);
	printf("lstr = %lf, lsts = %lf, \n", *lstr, *lsts);
	printf("ar =   %lf, as =   %lf \n", *ar, *as);
    }
}

lst_to_hm(lst, jd, h, m)
double lst, jd;
int *h, *m;
{
    double ed, gst, jzjd, t, r, b, t0, gmt;

    gst = lst + lon / 15.0;
    if (gst > 24.0)
	gst -= 24.0;
    jzjd = julian_date(1,0,yr);
    ed = jd-jzjd;
    t = (jzjd -2415020.0)/36525.0;
    r = 6.6460656+2400.05126*t+2.58E-05*t*t;
    b = 24-(r-24*(yr-1900));
    t0 = ed * 0.0657098 - b;
    if (t0 < 0.0)
	t0 += 24;
    gmt = gst-t0;
    if (gmt<0) 
	gmt += 24.0;
    gmt = gmt * 0.99727 - tz;;
    if (gmt < 0)
	gmt +=24.0;
    dh_to_hm(gmt, h, m);
}

dh_to_hm(dh, h, m)
double dh;
int *h, *m;
{
    double tempsec;

    *h = dh;
    *m = (dh - *h) * 60;
    tempsec = (dh - *h) * 60 - *m;
    tempsec = tempsec * 60 + 0.5;
    if (tempsec > 30)
	(*m)++;
    if (*m == 60) {
	*m = 0;
	(*h)++;
    }
}

eq_to_altaz(r, d, t, alt, az)
double r, d, t;
double *alt, *az;
{
    double p = 3.14159265;
    double r1 = p / 180.0;
    double b = lat * r1;
    double l = (360 - lon) * r1;
    double t5, s1, c1, c2, s2, a, h;

    if (debug)
	printf("Given R. A. = %lf, DECL. = %lf, gmt = %lf \n", r, d, t);

    r = r * 15.0 * r1;
    d = d * r1;
    t = t * 15.0 * r1;
    t5 = t - r + l;
    s1 = sin(b) * sin(d) + cos(b) * cos(d) * cos(t5);
    c1 = 1 - s1 * s1;
    if (c1 > 0) {
	c1 = sqrt(c1);
	h = atan(s1 / c1);
    } else {
	h = (s1 / fabs(s1)) * (p / 2.0);
    }
    c2 = cos(b) * sin(d) - sin(b) * cos(d) * cos(t5);
    s2 = -cos(d) * sin(t5);
    if (c2 == 0) 
	a = (s2/fabs(s2)) * (p/2);
    else {
	a = atan(s2/c2);
	if (c2 < 0)
	    a=a+p;
    }
    if (a<0)
        a=a+2*p;
    *alt = h / r1;
    *az = a / r1;

    if (debug)
	printf("alt = %lf, az = %lf \n",*alt,*az);
}

double
gmst(j, f)
double j,f;
{
    double d, j0, t, t1, t2, s;

    d = j - 2451545.0;
    t = d / 36525.0;
    t1 = floor(t);
    j0 = t1 * 36525.0 + 2451545.0;
    t2 = (j - j0 + 0.5)/36525.0;
    s = 24110.54841 + 184.812866 * t1; 
    s += 8640184.812866 * t2;
    s += 0.093104 * t * t;
    s -= 0.0000062 * t * t * t;
    s /= 86400.0;
    s -= floor(s);
    s = 24 * (s + (f - 0.5) * 1.002737909);
    if (s < 0)
	s += 24.0;
    if (s > 24.0)
	s -= 24.0;

    if (debug)
	printf("For jd = %lf, f = %lf, gst = %lf \n", j, f, s);

    return(s);
}
@EOF

chmod 644 sun/sun.c

if test -f sun/sun.1
then
    echo shar: sun/sun.1 already exists.  Stop!
    exit 1
fi
echo x - sun/sun.1
cat >sun/sun.1 <<'@EOF'
.TH SUN 1 "9 May 1985"
.UC 4
.SH NAME
sun \- calculate sunrise and sunset times
.SH SYNOPSIS
.B sun
[
.B \-p 
]
[
.B -t \fIh:m:s\fP 
]
[
.B -d \fIm/d/y\fP 
]
[
.B -a \fIlat\fP 
]
[
.B -o \fIlon\fP 
]
 [
.B -z \fItz\fP 
]
.LP
.SH DESCRIPTION
.I  Sun
Calculates the times of sunrise and sunset for the current system date.
Optionally,
.I sun
calculates the current position of the sun and its position at sunrise and
sunset for other dates, times and places.
.PP
The command line options are:
.TP
.B \-p 
Show current altitude and azimuth for the sun and its azimuth 
at sunrise and sunset.
.TP
.B -t \fIh:m:s\fP 
Use \fIh:m:s\fP as local hours (24 hour clock), minutes and  seconds as
the time instead of the current system time.
.TP
.B -d \fIm/d/y\fP 
Use \fIm/d/y\fP as the month, day and year instead of the current system date.
.TP
.B -a \fIlat\fP 
Use \fIlat\fP as the latitude of the observer, instead of the system latitude.
The latitude is specified in decimal degrees north.  For example, use 
45.5333 for Beaverton, Oregon.
.TP
.B -o \fIlon\fP 
Use \fIlon\fP as the longitude of the observer, instead of the system longitude.
The longitude is specified in decimal degrees west.  For example, use 
122.8333 for Beaverton, Oregon.
.TP
.B -z \fItz\fP 
Use \fItz\fP as the time zone of the observer, instead of the current system
timezone.  Timezone is specified as a positive number for locations west of
Greenwich.  For example, use 8 for Pacific Standard Time.
.SH AUTHOR
Robert Bond
.SH BUGS
Should figure out timezone and guess at longitude from the system time.  
Timezone, latitude and longitude are compiled in.
@EOF

chmod 444 sun/sun.1

chmod 755 sun

echo mkdir - today
mkdir today

if test -f today/moontx.c
then
    echo shar: today/moontx.c already exists.  Stop!
    exit 1
fi
echo x - today/moontx.c
cat >today/moontx.c <<'@EOF'
/****************************************************************************
 moon.c

     Phase of the Moon. Calculates the current phase of the moon.
     Based on routines from `Practical Astronomy with Your Calculator',
        by Duffett-Smith.
     Comments give the section from the book that particular piece
        of code was adapted from.

     -- Keith E. Brandt  VIII 1984

 ****************************************************************************/

# include	"moontx.h"

moontxt(buf)
char	buf[];
{
    char *cp=buf;

double dtor();
double adj360();
double potm();

long *lo = (long *) calloc (1, sizeof(long)); /* used by time calls */
struct tm *pt; /* ptr to time structure */

double days;   /* days since EPOCH */
double phase;  /* percent of lunar surface illuminated */
double phase2; /* percent of lunar surface illuminated one day later */
int i = EPOCH;

time (lo);  /* get system time */
pt = gmtime(lo);  /* get ptr to gmt time struct */
cfree(lo);

/* calculate days since EPOCH */
days = (pt->tm_yday +1) + ((pt->tm_hour + (pt->tm_min / 60.0)
       + (pt->tm_sec / 3600.0)) / 24.0);
while (i < pt->tm_year + 1900)
   days = days + 365 + ly(i++);

phase = potm(days);
sprintf(cp,"The Moon is ");
cp += strlen(buf);
if ((int)(phase + .5) == 100) {
   sprintf(cp,"Full");
   }
else if ((int)(phase + 0.5) == 0) 
   sprintf(cp,"New");
else if ((int)(phase + 0.5) == 50)  {
   phase2 = potm(++days);
   if (phase2 > phase)
      sprintf(cp,"at the First Quarter");
   else 
      sprintf(cp,"at the Last Quarter");
   }
else if ((int)(phase + 0.5) > 50) {
   phase2 = potm(++days);
   if (phase2 > phase)
      sprintf(cp,"Waxing ");
   else 
      sprintf(cp,"Waning ");
   cp = buf + strlen(buf);
   sprintf(cp,"Gibbous (%1.0f%% of Full)", phase);
   }
else if ((int)(phase + 0.5) < 50) {
   phase2 = potm(++days);
   if (phase2 > phase)
      sprintf(cp,"Waxing ");
   else
      sprintf(cp,"Waning ");
   cp = buf + strlen(buf);
   sprintf(cp,"Crescent (%1.0f%% of Full)", phase);
   }
}

double potm(days)
double days;
{
double N;
double Msol;
double Ec;
double LambdaSol;
double l;
double Mm;
double Ev;
double Ac;
double A3;
double Mmprime;
double A4;
double lprime;
double V;
double ldprime;
double D;
double Nm;

N = 360 * days / 365.2422;  /* sec 42 #3 */
adj360(&N);

Msol = N + EPSILONg - RHOg; /* sec 42 #4 */
adj360(&Msol);

Ec = 360 / PI * e * sin(dtor(Msol)); /* sec 42 #5 */

LambdaSol = N + Ec + EPSILONg;       /* sec 42 #6 */
adj360(&LambdaSol);

l = 13.1763966 * days + lzero;       /* sec 61 #4 */
adj360(&l);

Mm = l - (0.1114041 * days) - Pzero; /* sec 61 #5 */
adj360(&Mm);

Nm = Nzero - (0.0529539 * days);     /* sec 61 #6 */
adj360(&Nm);

Ev = 1.2739 * sin(dtor(2*(l - LambdaSol) - Mm)); /* sec 61 #7 */

Ac = 0.1858 * sin(dtor(Msol));       /* sec 61 #8 */
A3 = 0.37 * sin(dtor(Msol));

Mmprime = Mm + Ev - Ac - A3;         /* sec 61 #9 */

Ec = 6.2886 * sin(dtor(Mmprime));    /* sec 61 #10 */

A4 = 0.214 * sin(dtor(2 * Mmprime)); /* sec 61 #11 */

lprime = l + Ev + Ec - Ac + A4;      /* sec 61 #12 */

V = 0.6583 * sin(dtor(2 * (lprime - LambdaSol))); /* sec 61 #13 */

ldprime = lprime + V;                /* sec 61 #14 */

D = ldprime - LambdaSol;             /* sec 63 #2 */

return (50 * (1 - cos(dtor(D))));    /* sec 63 #3 */
}

ly(yr)
int yr;
{
/* returns 1 if leapyear, 0 otherwise */
return (yr % 4 == 0 && yr % 100 != 0 || yr % 400 == 0);
}

double dtor(deg)
double deg;
{
/* convert degrees to radians */
return (deg * PI / 180);
}

double adj360(deg)
double *deg;
{
/* adjust value so 0 <= deg <= 360 */
do if (*deg < 0)
   *deg += 360;
else if (*deg > 360)
   *deg -= 360;
while (*deg < 0 || *deg > 360);
}
@EOF

chmod 644 today/moontx.c

if test -f today/Makefile
then
    echo shar: today/Makefile already exists.  Stop!
    exit 1
fi
echo x - today/Makefile
cat >today/Makefile <<'@EOF'
##
#	Makefile for very verbose date command (today).
#
HOME	= /users/sun3/jad
BINDIR	= ${HOME}/bin
CFLAGS	= -sO
TODAY	= datetx.o moontx.o nbrtxt.o timetx.o today.o
POTM	= moontx.o potm.o
BIN	= potm today
LIB	= -lm

all:	${BIN}
potm:	${POTM}
	cc ${CFLAGS} -o $@ ${POTM} ${LIB}
today:	${TODAY}
	cc ${CFLAGS} -o $@ ${TODAY} ${LIB}
moontx.o:	moontx.h

install:	all
	mv -f ${BIN} ${BINDIR}
	rm -f ,* *.o ERRS core a.out

clean:
	rm -f ${BIN} a.out core ERRS ,* *.o
@EOF

chmod 644 today/Makefile

if test -f today/datetx.c
then
    echo shar: today/datetx.c already exists.  Stop!
    exit 1
fi
echo x - today/datetx.c
cat >today/datetx.c <<'@EOF'
/*
 *              Convert Date to Readable Format.
 *
 * Synopsis:
 *
 *      char    *datetxt(buffer, year, month, day);
 *      char    *buffer;        -- Output string goes here
 *      int     year;           -- Year,        1979 = 1979
 *      int     month;          -- Month,       January = 1
 *      int     day;            -- Day,         1 = 1
 *
 * The readable date will be written into the outpub buffer, terminated by
 * a null byte.  datetxt returns a pointer to the null byte.
 *
 * External routines called:
 *
 *      nbrtxt          (Number to ascii conversion)
 *      copyst          (String copy routine)
 */

extern  char    *nbrtxt();
extern  char    *copyst();
extern  char    *datetxt();

static char *daynames[] = {
	"Sunday",                       /* Sunday is day zero           */
	"Monday",
	"Tuesday",
	"Wednesday",
	"Thursday",
	"Friday",
	"Saturday",
};

static char *monthnames[] = {
	"?Nomember?",                   /* Illegal month                */
	"January",
	"February",
	"March",
	"April",
	"May",
	"June",
	"July",
	"August",
	"September",
	"October",
	"November",
	"December",
};

char *datetxt(buffer, year, month, day)
char    *buffer;                        /* Output goes here             */
int     year;                           /* Year, 1979 = 1979            */
int     month;                          /* Month of year, Jan = 1       */
int     day;                            /* Day in the month 1 = 1       */
/*
 * Output the date in readable format:
 *      Tuesday, the third of October
 */
{
	register char   *op;                    /* Output pointer       */

	op = buffer;                            /* Setup output pointer */
	op = copyst(op, daynames[dayofweek(year, month, day)]);
	op = copyst(op, ", the ");
	op = nbrtxt(op, day, 1);
	op = copyst(op, " day of ");
	op = copyst(op, monthnames[(month < 0 || month > 12) ? 0 : month]);
	op = copyst(op, ", ");
	if (year < 1000 || year >= 2000)
		return(nbrtxt(op, year, 0));
	else {
		op = nbrtxt(op, year/100, 0);
		op = copyst(op, " ");
		if ((year = year % 100) == 0)
			return(copyst(op, "hundred"));
		else
			return(nbrtxt(op, year, 0));
	}
}

dayofweek(year, month, day)
int     year;                                   /* Year, 1978 = 1978    */
int     month;                                  /* Month, January = 1   */
int     day;                                    /* Day of month, 1 = 1  */
/*
 * Return the day of the week on which this date falls: Sunday = 0.
 * Note, this routine is valid only for the Gregorian calender.
 */
{
	register int yearfactor;

	yearfactor = year + (month - 14)/12;
	return (( (13 * (month + 10 - (month + 10)/13*12) - 1)/5
		+ day + 77 + 5 * (yearfactor % 100)/4
		+ yearfactor / 400
		- yearfactor / 100 * 2) % 7);
}
@EOF

chmod 644 today/datetx.c

if test -f today/moontx.h
then
    echo shar: today/moontx.h already exists.  Stop!
    exit 1
fi
echo x - today/moontx.h
cat >today/moontx.h <<'@EOF'
# include	<stdio.h>
#ifdef	VAX
# include	<sys/time.h>
#else	VAX
# include	<time.h>
#endif	VAX
# include	<math.h>

#define EPOCH   1985
#define EPSILONg 279.611371     /* solar ecliptic long at EPOCH */
#define RHOg     282.680403     /* solar ecliptic long of perigee at EPOCH */
#define e          0.01671542   /* solar orbit eccentricity */
#define lzero     18.251907     /* lunar mean long at EPOCH */
#define Pzero    192.917585     /* lunar mean long of perigee at EPOCH */
#define Nzero     55.204723     /* lunar mean long of node at EPOCH */

# define	PI         3.141592654
@EOF

chmod 644 today/moontx.h

if test -f today/nbrtxt.c
then
    echo shar: today/nbrtxt.c already exists.  Stop!
    exit 1
fi
echo x - today/nbrtxt.c
cat >today/nbrtxt.c <<'@EOF'
/*
 *              Integer to Readable ASCII Conversion Routine.
 *
 * Synopsis:
 *
 *      char *nbrtxt(buffer, value, ordinal)
 *      char    *buffer;        -- The output buffer
 *      int     value;          -- The number to output
 *      int     ordinal;        -- Non-zero for ordinal number
 *
 *
 * The value is converted to a readable number and put in the output
 * buffer (null-terminated).  A pointer to the first free location
 * in the buffer (i.e., the null) is returned.  The ordinal
 * flag distinguishes between cardinal and ordinal numbers:
 *
 *      nbrtxt(buffer, 1, 0) = "one"
 *      nbrtxt(buffer, 1, 1) = "first"
 *
 * The longest output string is:
 *
 *      Twenty-seven thousand, three hundred and seventy-seventh.
 *
 *
 *
 *              Copy a String
 *
 * Synopsis
 *
 *      char *copyst(out, in)
 *      char    *out;           -- The output string
 *      char    *in;            -- The input string
 *
 * The input string is copied into the output string.  Copyst returns
 * a pointer to the null trailer.
 *
 */

extern char     *nbrtxt();
extern char     *copyst();

static char *cardinal[] = {
	"zero",
	"one",
	"two",
	"three",
	"four",
	"five",
	"six",
	"seven",
	"eight",
	"nine",
	"ten",
	"eleven",
	"twelve",
	"thirteen",
	"fourteen",
	"fifteen",
	"sixteen",
	"seventeen",
	"eighteen",
	"nineteen"
};

static char *ordinal[] = {
	"zeroth",
	"first",
	"second",
	"third",
	"fourth",
	"fifth",
	"sixth",
	"seventh",
	"eighth",
	"ninth",
	"tenth",
	"eleventh",
	"twelfth"
};

static char *twenties[] = {
	"twen",
	"thir",
	"for",
	"fif",
	"six",
	"seven",
	"eigh",
	"nine"
};

char *nbrtxt(buffer, datum, ordflag)
char    *buffer;                        /* Output string buffer         */
int     datum;                          /* what to translate            */
int     ordflag;                        /* 0 if cardinal, 1 if ordinal  */
/*
 * Translate a number to a readable text string, punctuation and all.
 * If ordflag is non-zero, ordinal numbers ("first, second") will
 * be generated, rather than cardinal ("one, two").
 * Note: nbrtxt() is recursive.
 */
{

	register int value;
	register char   *op;

	op = buffer;
	value = datum;
	if (value < 0) {
		op = copyst(op, "minus ");
		value = (-value);
		if (value < 0) {                /* Hack -32768          */
			op = copyst(op, twenties[1]);
			value = 2768;
		}
	}
	if (value >= 1000) {
		op = nbrtxt(op, value/1000, 0);
		op = copyst(op, " thousand");
		value = value % 1000;
		if (value == 0) goto exit;
		op = copyst(op, (value >= 100) ? ", " : " and ");
	}
	if (value >= 100) {
		op = copyst(op, cardinal[value/100]);
		op = copyst(op, " hundred");
		value = value % 100;
		if (value == 0) goto exit;
		op = copyst(op, " ");
	}
	if (value >= 20) {
		if (value == 90 && ordflag)
			return(copyst(op, "nintieth"));
		op = copyst(op, twenties[(value-20) / 10]);
		value = value % 10;
		if (value == 0) {
			return(copyst(op, (ordflag) ? "tieth" : "ty"));
		}
		op = copyst(op, "ty-");
	}
	if (value <= 12) {
		return(copyst(op,
			(ordflag) ? ordinal[value] : cardinal[value]));
	}
	op = copyst(op, cardinal[value]);       /* fourteen, fourteenth */
	/*
	 * Here on 100, 14000, etc.
	 */
exit:   if (ordflag) op = copyst(op, "th");
	return(op);
}

char *
copyst(buffer, string)
char    *buffer;
char    *string;
/*
 * Copy a string into buffer.  Return the free pointer.
 */
{
	register char   *ip;
	register char   *op;

	ip = string;
	op = buffer;

	while ((*op = *ip++)) op++;
	return (op);
}
@EOF

chmod 644 today/nbrtxt.c

if test -f today/timetx.c
then
    echo shar: today/timetx.c already exists.  Stop!
    exit 1
fi
echo x - today/timetx.c
cat >today/timetx.c <<'@EOF'
/*
 *              Convert Time to a Readable Format.
 *
 * Synopsis:
 *
 *      char    *timetxt(buffer, hour, minute, second, daylight);
 *      char    *buffer;        -- Where output goes
 *      int     hour;           -- Hour,        range is 0 to 24
 *      int     minute;         -- Minute,      range is -1 to 59
 *      int     second;         -- Seconds,     range is -1 to 59
 *      int     daylight;       -- Daylight savings time if non-zero.
 *
 * Note: if minute or second is less than zero, the value is not calculated.
 * This distinguishes between "unknown seconds" and "exactly no seconds."
 * If hour is less than zero, a null string is returned.
 * Timetxt converts the time to a null-trailed string.  It returns a pointer
 * to the first free byte (i.e. the null);
 *
 * The output follows the syntax of Robert J. Lurtsema, and includes:
 *
 *      In twenty-five seconds, the time will be ten minutes before noon.
 *
 *
 * External routines called:
 *
 *      nbrtxt          (Number to ascii conversion)
 *      copyst          (String copy routine)
 */

extern char     *nbrtxt();
extern char     *copyst();

char *timetxt(buffer, hour, minute, second, daylight)
char    *buffer;                        /* Output buffer                */
int     hour;                           /* Hours 00 - 23                */
int     minute;                         /* Minutes                      */
int     second;                         /* Seconds                      */
int     daylight;                       /* Non-zero if savings time     */
/*
 * Output time of day.
 */
{
	char            *op;            /* Output pointer               */
	register int    late;           /* after hour or afternoon      */
	register int	sec;		/* Seconds temp			*/
	char		*stuff();	/* Buffer stuffer		*/

	op = buffer;                    /* Setup buffer pointer         */
	if (hour < 0) {			/* If it's a dummy call,	*/
		*op = 0;		/* Return a null string		*/
		return(op);
	}
	if (daylight == 0101010) {      /* Secret flag                  */
		op = copyst(op, "The big hand is on the ");
		op = nbrtxt(op, (((minute + 2 + second/30)/5 + 11)%12)+1, 0);
		op = copyst(op," and the little hand is on the ");
		op = nbrtxt(op, ((hour + 11) % 12) + 1, 0);
		return(copyst(op, ".  "));
	}
	/*
	 * Check if the time is more than 30 minutes past the hour.
	 * If so, output the time before the next hour.
	 */
	if (minute < 0) second = (-2);  /* No minutes means no seconds  */
	else if ((late = (minute > 30 || (minute == 30 && second > 0)))) {
		if (second > 0) {       /* Before next hour             */
			second = 60 - second;
			minute += 1;    /* Diddle the minute, too       */
		}
		minute = 60 - minute;   /* Minutes before next hour     */
		hour += 1;              /* Frobozz next hour getter     */
	}
	/*
	 * Decisions, decisions:
	 *	Minutes	Seconds =>
	 *	  00	  00	Exactly Noon
	 *	  00	  01	One second after noon
	 *	  01	  00	Exactly one minute after noon
	 *	  30	  00	Exactly half past noon
	 *	  59	  00	Exactly one minute before noon
	 *	  59	  59	In one second, the time will be noon
	 */
	if (late && second > 0) {       /* Respectfully dedicated to    */
					/* Robert J. Lurtsema           */
		op = stuff(op, second, 1, "In ", " second");
		op = copyst(op, ", the time will be ");
		sec = -2;		/* We've done seconds already	*/
	}
	else {
		op = copyst(op, "The time is ");
		sec = second;		/* Seconds still to be done	*/
	}
	if (sec == 0) {
		op = copyst(op, "exactly ");
		if (minute == 30)
			op = copyst(op, "half past ");
		else	op = stuff(op, minute, 1, " ", " minute");
	}
	else {				/* Non exact or missing seconds	*/
		op = stuff(op, minute, 0, " ",     " minute");
	        op = stuff(op, sec, (minute > 0),  " and ", " second");
	}
	op = copyst(op, (minute < 0 || (minute == 0 && late)
			|| (second == 0
				&& ((minute == 0 && late == 0)
					|| minute == 30))) ? " "
		: (late) ? " before " : " after ");
	/*
	 * Hours are not quite so bad
	 */
	if (hour == 0 || hour == 24)
		op = copyst(op, "midnight");
	else if (hour == 12)
		op = copyst(op, "noon");
	else {
		if (late = (hour > 12))
			hour = hour - 12;
		op = nbrtxt(op, hour, 0);
		op = copyst(op, (late) ? " PM" : " AM");
	}
	return(copyst(op, (daylight)
		? ", Daylight Savings Time.  "
		: ", Digital Standard Time.  "));
}

static char *
stuff(buffer, value, flag, leading, trailing)
char    *buffer;                        /* Output goes here             */
int     value;                          /* The value to print if > 0    */
int     flag;                           /* flag is set to print leading */
char    *leading;                       /* preceeded by ...             */
char    *trailing;                      /* and followed by ...          */
/*
 * If value <= zero, output nothing. Else, output "leading" value "trailing".
 * Note: leading is output only if flag is set.
 * If value is not one, output an "s", too.
 */
{
	register char   *op;            /* Output pointer               */

	op = buffer;                    /* Setup buffer pointer         */
	if (value > 0) {
		if (flag)
			op = copyst(op, leading);
		op = nbrtxt(op, value, 0);
		op = copyst(op, trailing);
		if (value != 1)
			op = copyst(op, "s");
	}
	return(op);
}
@EOF

chmod 644 today/timetx.c

if test -f today/today.c
then
    echo shar: today/today.c already exists.  Stop!
    exit 1
fi
echo x - today/today.c
cat >today/today.c <<'@EOF'
/*
 *			T O D A Y
 *
 * time of day
 *
 * Define UNIX for "native" Unix
 */

/*)BUILD	$(PROGRAM)	= today
		$(FILES)	= { today datetx timetx nbrtxt moontx }
		$(TKBOPTIONS)	= {
			TASK	= ...TOD
		}
*/

#ifdef	DOCUMENTATION

title	today	Date and Time in English
index		Date and Time in English

synopsis

	today [-] [x] | [date]

description

	Today prints the date, time, and phase of the moon in English.
	The following options are available:
	.lm +8
	.s.i -8;- or x	Read date strings from the standard input file.
	.s.i -8;date	Print information for the indicated date.
	.s.lm -8
	Date and time information is given in ISO numeric notation.  For
	example, November 6, 1980 would be represented as "801106".  If
	a time is needed, it would be appended to the date, using 24-hour
	notation: "801106110402" would be a time which is exact to the
	second.  To specify the century, the two-digit century number
	may be preceeded by '+' as in "+18801106".
	.s
	Non-numeric separators between the various fields are permitted:
	"+1776.07.04-11:15:21".  Note that the full two digit entry must be
	given.
	.s
	If no parameter is given, today outputs the current date and time.

diagnostics

	.lm +8
	.s.i -8;Bad parameters or date out of range in ...
	.s
	An input date or time is incorrect.
	.lm -8

author

	Martin Minow

bugs

	The algorithm is only valid for the Gregorian calender.

#endif

#define	APRIL_FOOLS

int	__narg	=	1;		/* No prompt if no args		*/
#define LINEWIDTH       72              /* Width of line                */

#include <stdio.h>
#ifdef	VAX
#include <sys/time.h>
#else	VAX
#include <time.h>
#endif	VAX
#ifdef unix
#include <ctype.h>
#undef NULL
#endif

#define	NULL		0
#define	EOS		0
#define	FALSE		0
#define	TRUE		1

int day_month[] = {			/* Needed for dotexttime()      */
	0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int     ccpos;                          /* Current line position        */
char    lastbyte;                       /* Memory for output()          */
char    line[100];                      /* Data line for input function */
char    *valptr;                        /* Needed for number converter  */
char    wordbuffer[LINEWIDTH];          /* Buffer for output function   */
char    *wordptr = wordbuffer;          /* Free byte in wordbuffer      */
char	linebuffer[LINEWIDTH+2];	/* Output text buffer		*/
char	*lineptr = linebuffer;		/* Free byte in linebuffer	*/
int     polish;                         /* Funny mode flag              */

extern  char    *datetxt();             /* Date getter                  */
extern  char    *timetxt();             /* Time of day getter           */
extern  char    *moontxt();             /* Phase of the moon getter     */

main(argc, argv)
int     argc;
char    *argv[];
/*
 * Driver for time routines.  Usage:
 *
 *      today                   Prints current time of day in readable form,
 *                              followed by a cookie.
 *
 *      today {+cc}yymmddhhmmss Prints indicated time of day.
 *                              Note, hh, mm, ss may be omitted.
 *                              For example:
 *                                today 401106     = Nov. 6, 1940
 *                                today +19401106  = Nov. 6, 1940
 *                                today 4011061015 = Nov. 6, 1940 10:15 AM
 *
 *      today -                 Data is read from the standard input and
 *      today x                 output as needed.  The format of each
 *                              line is identical to the command format.
 *				("today x" is needed for vms.)
 */

{
	ccpos = 0;                      /* New line now                 */
	wordptr = wordbuffer;           /* Nothing buffered             */
	lineptr = linebuffer;		/* Nothing in output buffer too	*/
	polish = 0;			/* Normal mode			*/
	if (argc > 1 && tolower(argv[1][0]) == 'p') {
		polish = 1;
		argc--;
		argv++;
	}
	if (argc == 2 && ((argv[1][0] == '-') || (argv[1][0] | 040) == 'x')) {
		while (!getline()) {	/* Read and print times */
			dotexttime(line);
		}
		return;
	}
	else if (argc > 1) {
		if (dotexttime(argv[1]) == 0)
			return;
	}
	/*
	 * Here if no parameters or an error in the parameter field.
	 */
	dotime();			/* Print the time.              */
	output("\n");           	/* Space before cookie          */
#ifdef	UNIX
	execl(COOKIEPROGRAM, "cookie", 0);
#endif
}

dotime()
/*
 * Print the time of day for Unix or VMS native mode.
 */
{
	int     tvec[2];                /* Buffer for time function     */
	struct  tm *localtime();	/* Unix time decompile function */
	struct  tm *p;			/* Local pointer to time of day */
	int     year;
	int     month;
 
	time(tvec);                     /* Get the time of day          */
	p = localtime(tvec);            /* Make it more understandable  */
	year = p->tm_year + 1900;
	month = p->tm_mon + 1;
#ifdef	APRIL_FOOLS
	if (month == 4 && p->tm_mday == 1)
		polish = !polish;
#endif
	process(year, month, p->tm_mday, p->tm_hour,
 			p->tm_min, p->tm_sec, p->tm_isdst);
}

dotexttime(text)
char    *text;                          /* Time text                    */
/*
 * Create the time values and print them, return 1 on error.
 */

{
	int     epoch;                  /* Which century                */
	int     year;
	int     month;
	int     day;
	int     hour;
	int     minute;
	int     second;
	int     leapyear;

	valptr = text;                          /* Setup for getval()   */
	while (*valptr == ' ') valptr++;        /* Leading blanks skip  */
	if (*valptr != '+')
		epoch = 1900;                   /* Default for now      */
	else {
		valptr++;
		if ((epoch = getval(-1, 00, 99)) < 0) goto bad;
		epoch *= 100;                   /* Make it a real epoch */
	}

	if ((year = getval(-1, 00, 99)) < 0) goto bad;
	year += epoch;
	leapyear = ((year%4) == 0) && (((year%400) == 0) || (year%100 != 0));
	if ((month = getval(-1, 1, 12)) < 0) goto bad;
	if ((day = getval(-1, 1,
		(month == 2 && leapyear) ? 29 : day_month[month])) < 0)
			goto bad;
	if ((hour = getval(-2, 0, 23)) == -1) goto bad;
	if ((minute = getval(-2, 0, 59)) == -1) goto bad;
	if ((second = getval(-2, 0, 59)) == -1) goto bad;
	process(year, month, day, hour, minute, second, 0);
	return(0);				/* Normal exit		*/

bad:    output("Bad parameters or date out of range in \"");
	output(text);
	output("\" after scanning \"");
	*valptr = '\0';
	output(text);
	output("\".\n");
	return(1);				/* Error exit		*/
}

static	char    outline[500];		/* Output buffer                */

process(year, month, day, hour, minute, second, daylight)
int     year;                           /* Year		1900 = 1900	*/
int     month;                          /* Month	January = 1	*/
int     day;                            /* Day		1 = 1		*/
int	hour;				/* Hour		0 .. 23		*/
int	minute;				/* Minute	0 .. 59		*/
int	second;				/* Second	0 .. 59		*/
int	daylight;			/* Daylight savings time if 1	*/
/*
 * Output the information.  Note that the parameters are within range.
 */
{

	output("Today is ");
	datetxt(outline, year, month, day);
	output(outline);
	output(".  ");
	timetxt(outline, hour, minute, second,
			(polish) ? 0101010 : daylight);
	output(outline);
/*	output("The moon is ");			*/
/*	moontxt(outline, year, month, day);	*/
	moontxt(outline);	/* replaced by smarter version */
	output(outline);
	output(".\n");
}


output(text)
char    *text;                                  /* What to print        */
/*
 * Output routine.  Text is output using put() so that lines are
 * not more than LINEWIDTH bytes long.  Current position is in global ccpos.
 * (put is equivalent to putchar() except that it is locally buffered.)
 */
{
	register char	*in;                    /* Current pos. in scan */
	register char	c;                      /* Current character    */
	register char	*wp;			/* Word pointer		*/

	in = text;
	while (c = *in++) {
		switch (c) {
		case '\n':                      /* Force new line       */
		case ' ':                       /* or a space seen      */
			if ((wordptr-wordbuffer) + ccpos >= LINEWIDTH) {
				put('\n');  /* Current word         */
				ccpos = 0;      /* won't fit, dump it.  */
			}
			if (wordptr > wordbuffer) {
				if (ccpos) {	/* Leading space needed */
					put(' ');
					ccpos++;
				}
				for (wp = wordbuffer; wp < wordptr;) {
					put(*wp++);
				}
				ccpos += (wordptr - wordbuffer);
				wordptr = wordbuffer;	/* Empty buffer	*/
			}
			if (c == '\n') {
				put('\n');	/* Print a newline	*/
				ccpos = 0;	/* and reset the cursor	*/
			}
			break;

		default:
			*wordptr++ = c;         /* Save piece of word   */
		}
	}
}

put(c)
register char	c;
/*
 * Actual output routine
 */
{
	if (c == '\n' || (lineptr - linebuffer) >= LINEWIDTH) {
		*lineptr = EOS;
		puts(linebuffer);
		lineptr = linebuffer;
		if (c == '\n')
			return;
	}
	*lineptr++ = c;
} 

getline()
/*
 * Read text to global line[].  Return 1 on end of file, zero on ok.
 */
{
	register char *t;

	return (gets(line) == NULL);
}

getval(flag, low, high)
int     flag;
int     low;
int     high;
/*
 * Global valptr points to a 2-digit positive decimal integer.
 * Skip over leading non-numbers and return the value.
 * Return flag if text[0] == '\0'. Return -1 if the text is bad,
 * or if the value is out of the low:high range.
 */
{
	register int value;
	register int i;
	register int temp;

	if (*valptr == '\0') return(flag);        /* Default?             */
	while (*valptr && (*valptr < '0' || *valptr > '9')) *valptr++;
				/* The above allows for 78.04.22 format */
	for (value = i = 0; i < 2; i++) {
		temp = *valptr++ - '0';
		if (temp < 0 || temp > 9) return(-1);
		value = (value*10) + temp;
	}
	return((value >= low && value <= high) ? value : -1);
}

@EOF

chmod 644 today/today.c

if test -f today/potm.c
then
    echo shar: today/potm.c already exists.  Stop!
    exit 1
fi
echo x - today/potm.c
cat >today/potm.c <<'@EOF'
/*
**	<potm.c> --	Print out the phase of the moon ...
**
**	programmer:	John Dilley	(mordred:jad)
**
**	creation date:	Sat Feb  9 14:27
**
**
**	modification history
**
*/

static	char	potm[64];

main()
{
    moontxt(potm);
    printf("Phase-of-the-Moon:%s\n", potm+11);
}
@EOF

chmod 644 today/potm.c

chmod 755 today

exit 0
/* ---------- */