From 5971fdddb9b4d081b8f1e1efcd11815cc4ec3440 Mon Sep 17 00:00:00 2001 From: jsm Date: Tue, 14 Sep 1999 20:00:07 +0000 Subject: Update pom to the third edition of Duffett-Smith's book, and clean it up somewhat. Change time specification format to similar to that used by date(1) - taking a command line argument in seconds since the Epoch is silly. Date parsing based on code from date(1). Based on work by Paul Janzen for OpenBSD. --- pom/pom.6 | 36 ++++++++----- pom/pom.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 155 insertions(+), 57 deletions(-) (limited to 'pom') diff --git a/pom/pom.6 b/pom/pom.6 index 4a4ce04a..42f663d7 100644 --- a/pom/pom.6 +++ b/pom/pom.6 @@ -1,4 +1,4 @@ -.\" $NetBSD: pom.6,v 1.6 1998/06/13 01:09:22 jeremy Exp $ +.\" $NetBSD: pom.6,v 1.7 1999/09/14 20:00:07 jsm Exp $ .\" .\" Copyright (c) 1989, 1993 .\" The Regents of the University of California. All rights reserved. @@ -33,7 +33,7 @@ .\" .\" @(#)pom.6 8.1 (Berkeley) 5/31/93 .\" -.Dd May 31, 1993 +.Dd January 9, 1999 .Dt POM 6 .Os .Sh NAME @@ -41,7 +41,7 @@ .Nd display the phase of the moon .Sh SYNOPSIS .Nm -.Op Ar secs +.Op [[[[[cc]yy]mm]dd]HH] .Sh DESCRIPTION The .Nm @@ -49,13 +49,25 @@ utility displays the current phase of the moon. Useful for selecting software completion target dates and predicting managerial behavior. .Pp -.Bl -tag -width secs -.It Ar secs -Display the phase of the moon for the date represented by -.Ar secs -seconds past the Epoch -(Midnight, January 1, 1970 GMT). -If -.Ar secs -is unspecified, the current time is used. +.Bl -tag -width [[[[[cc]yy]mm]dd]HH] +.It Ar [[[[[cc]yy]mm]dd]HH] +Display the phase of the moon for a given time. The format is similar to +the canonical representation used by +.Xr date 1 . .El +.Sh SEE ALSO +.Xr date 1 +.Sh AUTHOR +.Nm +was written by Keith E. Brandt. +.Sh BUGS +Times must be within range of the +.Ux +epoch. +.Pp +This program does not allow for the difference between the TDT and +UTC timescales (about one minute at the time of writing). +.Sh ACKNOWLEDGEMENTS +This program is based on algorithms from +.%B Practical Astronomy with Your Calculator, Third Edition +by Peter Duffett-Smith . diff --git a/pom/pom.c b/pom/pom.c index 050c937a..97a946d4 100644 --- a/pom/pom.c +++ b/pom/pom.c @@ -1,4 +1,4 @@ -/* $NetBSD: pom.c,v 1.11 1998/09/11 14:07:04 hubertf Exp $ */ +/* $NetBSD: pom.c,v 1.12 1999/09/14 20:00:07 jsm Exp $ */ /* * Copyright (c) 1989, 1993 @@ -45,7 +45,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ #if 0 static char sccsid[] = "@(#)pom.c 8.1 (Berkeley) 5/31/93"; #else -__RCSID("$NetBSD: pom.c,v 1.11 1998/09/11 14:07:04 hubertf Exp $"); +__RCSID("$NetBSD: pom.c,v 1.12 1999/09/14 20:00:07 jsm Exp $"); #endif #endif /* not lint */ @@ -57,60 +57,71 @@ __RCSID("$NetBSD: pom.c,v 1.11 1998/09/11 14:07:04 hubertf Exp $"); * * -- Keith E. Brandt VIII 1984 * + * Updated to the Third Edition of Duffett-Smith's book, Paul Janzen, IX 1998 + * */ -#include +#include #include -#include #include #include #include #include -#include +#include +#include #ifndef PI #define PI 3.14159265358979323846 #endif -#define EPOCH 85 /* really 1985 */ -#define EPSILONg 279.611371 /* solar ecliptic long at EPOCH */ -#define RHOg 282.680403 /* solar ecliptic long of perigee at EPOCH */ -#define ECCEN 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 */ + +/* + * The EPOCH in the third edition of the book is 1990 Jan 0.0 TDT. + * In this program, we do not bother to correct for the differences + * between UTC (as shown by the UNIX clock) and TDT. (TDT = TAI + 32.184s; + * TAI-UTC = 32s in Jan 1999.) + */ +#define EPOCH_MINUS_1970 (20 * 365 + 5 - 1) /* 20 years, 5 leaps, back 1 day to Jan 0 */ +#define EPSILONg 279.403303 /* solar ecliptic long at EPOCH */ +#define RHOg 282.768422 /* solar ecliptic long of perigee at EPOCH */ +#define ECCEN 0.016713 /* solar orbit eccentricity */ +#define lzero 318.351648 /* lunar mean long at EPOCH */ +#define Pzero 36.340410 /* lunar mean long of perigee at EPOCH */ +#define Nzero 318.510107 /* lunar mean long of node at EPOCH */ void adj360 __P((double *)); double dtor __P((double)); int main __P((int, char *[])); double potm __P((double)); +time_t parsetime __P((char *)); +void badformat __P((void)) __attribute__((__noreturn__)); int main(argc, argv) int argc; char *argv[]; { - struct timeval tp; - struct timezone tzp; - struct tm *GMT; - time_t tmpt; + time_t tmpt, now; double days, today, tomorrow; - int cnt; + char buf[1024]; + if (time(&now) == (time_t)-1) + err(1, "time"); if (argc > 1) { - tp.tv_sec = atoi(argv[1]); - tp.tv_usec = 0; + tmpt = parsetime(argv[1]); + strftime(buf, sizeof(buf), "%a %Y %b %e %H:%M:%S (%Z)", + localtime(&tmpt)); + printf("%s: ", buf); } else { - if (gettimeofday(&tp,&tzp)) - err(1, "gettimeofday"); + tmpt = now; } - tmpt = tp.tv_sec; - GMT = gmtime(&tmpt); - days = (GMT->tm_yday + 1) + ((GMT->tm_hour + - (GMT->tm_min / 60.0) + (GMT->tm_sec / 3600.0)) / 24.0); - for (cnt = EPOCH; cnt < GMT->tm_year; ++cnt) - days += isleap(cnt + 1900) ? 366 : 365; + days = (tmpt - EPOCH_MINUS_1970 * 86400) / 86400.0; today = potm(days) + .5; - (void)printf("The Moon is "); + if (tmpt < now) + (void)printf("The Moon was "); + else if (tmpt == now) + (void)printf("The Moon is "); + else + (void)printf("The Moon will be "); if ((int)today == 100) (void)printf("Full\n"); else if (!(int)today) @@ -120,7 +131,11 @@ main(argc, argv) if ((int)today == 50) (void)printf("%s\n", tomorrow > today ? "at the First Quarter" : "at the Last Quarter"); + /* today is 0.5 too big, but it doesn't matter here + * since the phase is changing fast enough + */ else { + today -= 0.5; /* Now it might matter */ (void)printf("%s ", tomorrow > today ? "Waxing" : "Waning"); if (today > 50) @@ -145,30 +160,30 @@ potm(days) double N, Msol, Ec, LambdaSol, l, Mm, Ev, Ac, A3, Mmprime; double A4, lprime, V, ldprime, D, Nm; - N = 360 * days / 365.2422; /* sec 42 #3 */ + N = 360 * days / 365.242191; /* sec 46 #3 */ adj360(&N); - Msol = N + EPSILONg - RHOg; /* sec 42 #4 */ + Msol = N + EPSILONg - RHOg; /* sec 46 #4 */ adj360(&Msol); - Ec = 360 / PI * ECCEN * sin(dtor(Msol)); /* sec 42 #5 */ - LambdaSol = N + Ec + EPSILONg; /* sec 42 #6 */ + Ec = 360 / PI * ECCEN * sin(dtor(Msol)); /* sec 46 #5 */ + LambdaSol = N + Ec + EPSILONg; /* sec 46 #6 */ adj360(&LambdaSol); - l = 13.1763966 * days + lzero; /* sec 61 #4 */ + l = 13.1763966 * days + lzero; /* sec 65 #4 */ adj360(&l); - Mm = l - (0.1114041 * days) - Pzero; /* sec 61 #5 */ + Mm = l - (0.1114041 * days) - Pzero; /* sec 65 #5 */ adj360(&Mm); - Nm = Nzero - (0.0529539 * days); /* sec 61 #6 */ + Nm = Nzero - (0.0529539 * days); /* sec 65 #6 */ adj360(&Nm); - Ev = 1.2739 * sin(dtor(2*(l - LambdaSol) - Mm)); /* sec 61 #7 */ - Ac = 0.1858 * sin(dtor(Msol)); /* sec 61 #8 */ + Ev = 1.2739 * sin(dtor(2*(l - LambdaSol) - Mm)); /* sec 65 #7 */ + Ac = 0.1858 * sin(dtor(Msol)); /* sec 65 #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 */ + Mmprime = Mm + Ev - Ac - A3; /* sec 65 #9 */ + Ec = 6.2886 * sin(dtor(Mmprime)); /* sec 65 #10 */ + A4 = 0.214 * sin(dtor(2 * Mmprime)); /* sec 65 #11 */ + lprime = l + Ev + Ec - Ac + A4; /* sec 65 #12 */ + V = 0.6583 * sin(dtor(2 * (lprime - LambdaSol))); /* sec 65 #13 */ + ldprime = lprime + V; /* sec 65 #14 */ + D = ldprime - LambdaSol; /* sec 67 #2 */ + return(50.0 * (1 - cos(dtor(D)))); /* sec 67 #3 */ } /* @@ -198,3 +213,74 @@ adj360(deg) else break; } + +#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2; +time_t +parsetime(p) + char *p; +{ + struct tm *lt; + int bigyear; + int yearset = 0; + time_t tval; + unsigned char *t; + + for (t = p; *t; ++t) { + if (isdigit(*t)) + continue; + badformat(); + } + + tval = time(NULL); + lt = localtime(&tval); + lt->tm_sec = 0; + lt->tm_min = 0; + + switch (strlen(p)) { + case 10: /* yyyy */ + bigyear = ATOI2(p); + lt->tm_year = bigyear * 100 - 1900; + yearset = 1; + /* FALLTHROUGH */ + case 8: /* yy */ + if (yearset) { + lt->tm_year += ATOI2(p); + } else { + lt->tm_year = ATOI2(p); + if (lt->tm_year < 69) /* hack for 2000 */ + lt->tm_year += 100; + } + /* FALLTHROUGH */ + case 6: /* mm */ + lt->tm_mon = ATOI2(p); + if ((lt->tm_mon > 12) || !lt->tm_mon) + badformat(); + --lt->tm_mon; /* time struct is 0 - 11 */ + /* FALLTHROUGH */ + case 4: /* dd */ + lt->tm_mday = ATOI2(p); + if ((lt->tm_mday > 31) || !lt->tm_mday) + badformat(); + /* FALLTHROUGH */ + case 2: /* HH */ + lt->tm_hour = ATOI2(p); + if (lt->tm_hour > 23) + badformat(); + break; + default: + badformat(); + } + /* The calling code needs a valid tm_ydays and this is the easiest + * way to get one */ + if ((tval = mktime(lt)) == -1) + errx(1, "specified date is outside allowed range"); + return (tval); +} + +void +badformat() +{ + warnx("illegal time format"); + (void)fprintf(stderr, "usage: pom [[[[[cc]yy]mm]dd]HH]\n"); + exit(1); +} -- cgit v1.2.3-56-ge451