Index: user/edwin/calendar/calendar.h =================================================================== --- user/edwin/calendar/calendar.h (revision 204262) +++ user/edwin/calendar/calendar.h (revision 204263) @@ -1,197 +1,199 @@ /*- * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #define SECSPERDAY (24 * 60 * 60) #define SECSPERHOUR (60 * 60) #define SECSPERMINUTE (60) +#define MINSPERHOUR (60) #define HOURSPERDAY (24) #define FSECSPERDAY (24.0 * 60.0 * 60.0) #define FSECSPERHOUR (60.0 * 60.0) #define FSECSPERMINUTE (60.0) +#define FMINSPERHOUR (60.0) #define FHOURSPERDAY (24.0) #define DAYSPERYEAR 365 #define DAYSPERLEAPYEAR 366 /* Not yet categorized */ extern struct passwd *pw; extern int doall; extern struct iovec header[]; extern struct tm tp1, tp2; extern time_t t1, t2; extern const char *calendarFile; extern int yrdays; extern struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon; extern struct fixs nmarequinox, nsepequinox, njunsolstice, ndecsolstice; extern double UTCoffset; extern int eastlongitude; #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) /* Flags to determine the returned values by determinestyle() in parsedata.c */ #define F_NONE 0x00000 #define F_MONTH 0x00001 #define F_DAYOFWEEK 0x00002 #define F_DAYOFMONTH 0x00004 #define F_MODIFIERINDEX 0x00008 #define F_MODIFIEROFFSET 0x00010 #define F_SPECIALDAY 0x00020 #define F_ALLMONTH 0x00040 #define F_ALLDAY 0x00080 #define F_VARIABLE 0x00100 #define F_EASTER 0x00200 #define F_CNY 0x00400 #define F_PASKHA 0x00800 #define F_NEWMOON 0x01000 #define F_FULLMOON 0x02000 #define F_MAREQUINOX 0x04000 #define F_SEPEQUINOX 0x08000 #define F_JUNSOLSTICE 0x10000 #define F_DECSOLSTICE 0x20000 #define STRING_EASTER "Easter" #define STRING_PASKHA "Paskha" #define STRING_CNY "ChineseNewYear" #define STRING_NEWMOON "NewMoon" #define STRING_FULLMOON "FullMoon" #define STRING_MAREQUINOX "MarEquinox" #define STRING_SEPEQUINOX "SepEquinox" #define STRING_JUNSOLSTICE "JunSolstice" #define STRING_DECSOLSTICE "DecSolstice" #define MAXCOUNT 125 /* Random number of maximum number of * repeats of an event. Should be 52 * (number of weeks per year), if you * want to show two years then it * should be 104. If you are seeing * more than this you are using this * program wrong. */ /* * All the astronomical calculations are carried out for the meridian 120 * degrees east of Greenwich. */ #define UTCOFFSET_CNY 8.0 extern int debug; /* show parsing of the input */ extern int f_dayAfter; /* days after current date */ extern int f_dayBefore; /* days before current date */ extern int Friday; /* day before weekend */ extern int year1, year2; /* events.c */ /* * Event sorting related functions: * - Use event_add() to create a new event * - Use event_continue() to add more text to the last added event * - Use event_print_all() to display them in time chronological order */ struct event *event_add(int, int, int, char *, int, char *, char *); void event_continue(struct event *events, char *txt); void event_print_all(FILE *fp); struct event { int year; int month; int day; int var; char *date; char *text; char *extra; struct event *next; }; /* locale.c */ struct fixs { char *name; int len; }; extern struct fixs fndays[8]; /* full national days names */ extern struct fixs ndays[8]; /* short national days names */ extern struct fixs fnmonths[13]; /* full national months names */ extern struct fixs nmonths[13]; /* short national month names */ extern const char *months[]; extern const char *fmonths[]; extern const char *days[]; extern const char *fdays[]; void setnnames(void); /* day.c */ extern const struct tm tm0; void settimes(time_t,int, int, struct tm *tp1, struct tm *tp2); time_t Mktime(char *); /* parsedata.c */ int parsedaymonth(char *, int *, int *, int *, int *, char **); void dodebug(char *type); /* io.c */ void cal(void); void closecal(FILE *); FILE *opencal(void); /* ostern.c / pashka.c */ int paskha(int); int easter(int); /* dates.c */ extern int cumdaytab[][14]; extern int mondaytab[][14]; extern int debug_remember; void generatedates(struct tm *tp1, struct tm *tp2); void dumpdates(void); int remember_ymd(int y, int m, int d); int remember_yd(int y, int d, int *rm, int *rd); int first_dayofweek_of_year(int y); int first_dayofweek_of_month(int y, int m); int walkthrough_dates(struct event **e); void addtodate(struct event *e, int year, int month, int day); /* pom.c */ #define MAXMOONS 18 void pom(int year, double UTCoffset, int *fms, int *nms); void fpom(int year, double utcoffset, double *ffms, double *fnms); /* sunpos.c */ void equinoxsolstice(int year, double UTCoffset, int *equinoxdays, int *solsticedays); void fequinoxsolstice(int year, double UTCoffset, double *equinoxdays, double *solsticedays); int calculatesunlongitude30(int year, int degreeGMToffset, int *ichinesemonths); Index: user/edwin/calendar/cny.c =================================================================== --- user/edwin/calendar/cny.c (revision 204262) +++ user/edwin/calendar/cny.c (revision 204263) Property changes on: user/edwin/calendar/cny.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: user/edwin/calendar/dates.c =================================================================== --- user/edwin/calendar/dates.c (revision 204262) +++ user/edwin/calendar/dates.c (revision 204263) @@ -1,452 +1,452 @@ /*- * Copyright (c) 1992-2009 Edwin Groothuis. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include -__FBSDID("$FreeBSD: user/edwin/calendar/calendar.c 201195 2009-12-29 13:14:13Z edwin $"); +__FBSDID("$FreeBSD$"); #include #include #include #include #include "calendar.h" struct cal_year { int year; /* 19xx, 20xx, 21xx */ int easter; /* Julian day */ int paskha; /* Julian day */ int cny; /* Julian day */ int firstdayofweek; /* 0 .. 6 */ struct cal_month *months; struct cal_year *nextyear; } cal_year; struct cal_month { int month; /* 01 .. 12 */ int firstdayjulian; /* 000 .. 366 */ int firstdayofweek; /* 0 .. 6 */ struct cal_year *year; /* points back */ struct cal_day *days; struct cal_month *nextmonth; } cal_month; struct cal_day { int dayofmonth; /* 01 .. 31 */ int julianday; /* 000 .. 366 */ int dayofweek; /* 0 .. 6 */ struct cal_day *nextday; struct cal_month *month; /* points back */ struct cal_year *year; /* points back */ struct event *events; } cal_day; int debug_remember = 0; struct cal_year *hyear = NULL; /* 1-based month, 0-based days, cumulative */ int *cumdays; int cumdaytab[][14] = { {0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364}, {0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, }; /* 1-based month, individual */ int *mondays; int mondaytab[][14] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30}, }; static struct cal_day * find_day(int yy, int mm, int dd); static void createdate(int y, int m, int d) { struct cal_year *py, *pyp; struct cal_month *pm, *pmp; struct cal_day *pd, *pdp; int *cumday; pyp = NULL; py = hyear; while (py != NULL) { if (py->year == y + 1900) break; pyp = py; py = py->nextyear; } if (py == NULL) { struct tm td; time_t t; py = (struct cal_year *)calloc(1, sizeof(struct cal_year)); py->year = y + 1900; py->easter = easter(y); py->paskha = paskha(y); td = tm0; td.tm_year = y; td.tm_mday = 1; t = mktime(&td); localtime_r(&t, &td); py->firstdayofweek = td.tm_wday; if (pyp != NULL) pyp->nextyear = py; } if (pyp == NULL) { /* The very very very first one */ hyear = py; } pmp = NULL; pm = py->months; while (pm != NULL) { if (pm->month == m) break; pmp = pm; pm = pm->nextmonth; } if (pm == NULL) { pm = (struct cal_month *)calloc(1, sizeof(struct cal_month)); pm->year = py; pm->month = m; cumday = cumdaytab[isleap(y)]; pm->firstdayjulian = cumday[m] + 2; pm->firstdayofweek = (py->firstdayofweek + pm->firstdayjulian -1) % 7; if (pmp != NULL) pmp->nextmonth = pm; } if (pmp == NULL) py->months = pm; pdp = NULL; pd = pm->days; while (pd != NULL) { pdp = pd; pd = pd->nextday; } if (pd == NULL) { /* Always true */ pd = (struct cal_day *)calloc(1, sizeof(struct cal_day)); pd->month = pm; pd->year = py; pd->dayofmonth = d; pd->julianday = pm->firstdayjulian + d - 1; pd->dayofweek = (pm->firstdayofweek + d - 1) % 7; if (pdp != NULL) pdp->nextday = pd; } if (pdp == NULL) pm->days = pd; } void generatedates(struct tm *tp1, struct tm *tp2) { int y1, m1, d1; int y2, m2, d2; int y, m, d; int *mondays; y1 = tp1->tm_year; m1 = tp1->tm_mon + 1; d1 = tp1->tm_mday; y2 = tp2->tm_year; m2 = tp2->tm_mon + 1; d2 = tp2->tm_mday; if (y1 == y2) { if (m1 == m2) { /* Same year, same month. Easy! */ for (d = d1; d <= d2; d++) createdate(y1, m1, d); return; } /* * Same year, different month. * - Take the leftover days from m1 * - Take all days from * - Take the first days from m2 */ mondays = mondaytab[isleap(y1)]; for (d = d1; d <= mondays[m1]; d++) createdate(y1, m1, d); for (m = m1 + 1; m < m2; m++) for (d = 1; d <= mondays[m]; d++) createdate(y1, m, d); for (d = 1; d <= d2; d++) createdate(y1, m2, d); return; } /* * Different year, different month. * - Take the leftover days from y1-m1 * - Take all days from y1- * - Take all days from y2-[1 .. m2> * - Take the first days of y2-m2 */ mondays = mondaytab[isleap(y1)]; for (d = d1; d <= mondays[m1]; d++) createdate(y1, m1, d); for (m = m1 + 1; m <= 12; m++) for (d = 1; d <= mondays[m]; d++) createdate(y1, m, d); for (y = y1 + 1; y < y2; y++) { mondays = mondaytab[isleap(y)]; for (m = 1; m <= 12; m++) for (d = 1; d <= mondays[m]; d++) createdate(y, m, d); } mondays = mondaytab[isleap(y2)]; for (m = 1; m < m2; m++) for (d = 1; d <= mondays[m]; d++) createdate(y2, m, d); for (d = 1; d <= d2; d++) createdate(y2, m2, d); } void dumpdates(void) { struct cal_year *y; struct cal_month *m; struct cal_day *d; y = hyear; while (y != NULL) { printf("%-5d (wday:%d)\n", y->year, y->firstdayofweek); m = y->months; while (m != NULL) { printf("-- %-5d (julian:%d, dow:%d)\n", m->month, m->firstdayjulian, m->firstdayofweek); d = m->days; while (d != NULL) { printf(" -- %-5d (julian:%d, dow:%d)\n", d->dayofmonth, d->julianday, d->dayofweek); d = d->nextday; } m = m->nextmonth; } y = y->nextyear; } } int remember_ymd(int yy, int mm, int dd) { struct cal_year *y; struct cal_month *m; struct cal_day *d; if (debug_remember) printf("remember_ymd: %d - %d - %d\n", yy, mm, dd); y = hyear; while (y != NULL) { if (y->year != yy) { y = y->nextyear; continue; } m = y->months; while (m != NULL) { if (m->month != mm) { m = m->nextmonth; continue; } d = m->days; while (d != NULL) { if (d->dayofmonth == dd) return (1); d = d->nextday; continue; } return (0); } return (0); } return (0); } int remember_yd(int yy, int dd, int *rm, int *rd) { struct cal_year *y; struct cal_month *m; struct cal_day *d; if (debug_remember) printf("remember_yd: %d - %d\n", yy, dd); y = hyear; while (y != NULL) { if (y->year != yy) { y = y->nextyear; continue; } m = y->months; while (m != NULL) { d = m->days; while (d != NULL) { if (d->julianday == dd) { *rm = m->month; *rd = d->dayofmonth; return (1); } d = d->nextday; } m = m->nextmonth; } return (0); } return (0); } int first_dayofweek_of_year(int yy) { struct cal_year *y; y = hyear; while (y != NULL) { if (y->year == yy) return (y->firstdayofweek); y = y->nextyear; } /* Should not happen */ return (-1); } int first_dayofweek_of_month(int yy, int mm) { struct cal_year *y; struct cal_month *m; y = hyear; while (y != NULL) { if (y->year != yy) { y = y->nextyear; continue; } m = y->months; while (m != NULL) { if (m->month == mm) return (m->firstdayofweek); m = m->nextmonth; } /* Should not happen */ return (-1); } /* Should not happen */ return (-1); } int walkthrough_dates(struct event **e) { static struct cal_year *y = NULL; static struct cal_month *m = NULL; static struct cal_day *d = NULL; if (y == NULL) { y = hyear; m = y->months; d = m->days; *e = d->events; return (1); }; if (d->nextday != NULL) { d = d->nextday; *e = d->events; return (1); } if (m->nextmonth != NULL) { m = m->nextmonth; d = m->days; *e = d->events; return (1); } if (y->nextyear != NULL) { y = y->nextyear; m = y->months; d = m->days; *e = d->events; return (1); } return (0); } static struct cal_day * find_day(int yy, int mm, int dd) { struct cal_year *y; struct cal_month *m; struct cal_day *d; if (debug_remember) printf("remember_ymd: %d - %d - %d\n", yy, mm, dd); y = hyear; while (y != NULL) { if (y->year != yy) { y = y->nextyear; continue; } m = y->months; while (m != NULL) { if (m->month != mm) { m = m->nextmonth; continue; } d = m->days; while (d != NULL) { if (d->dayofmonth == dd) return (d); d = d->nextday; continue; } return (NULL); } return (NULL); } return (NULL); } void addtodate(struct event *e, int year, int month, int day) { struct cal_day *d; d = find_day(year, month, day); e->next = d->events; d->events = e; } Property changes on: user/edwin/calendar/dates.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: user/edwin/calendar/events.c =================================================================== --- user/edwin/calendar/events.c (revision 204262) +++ user/edwin/calendar/events.c (revision 204263) @@ -1,125 +1,125 @@ /*- * Copyright (c) 1992-2009 Edwin Groothuis. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include -__FBSDID("$FreeBSD: user/edwin/calendar/io.c 200813 2009-12-21 21:17:59Z edwin $"); +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include "pathnames.h" #include "calendar.h" struct event * event_add(int year, int month, int day, char *date, int var, char *txt, char *extra) { struct event *e; /* * Creating a new event: * - Create a new event * - Copy the machine readable day and month * - Copy the human readable and language specific date * - Copy the text of the event */ e = (struct event *)calloc(1, sizeof(struct event)); if (e == NULL) errx(1, "event_add: cannot allocate memory"); e->month = month; e->day = day; e->var = var; e->date = strdup(date); if (e->date == NULL) errx(1, "event_add: cannot allocate memory"); e->text = strdup(txt); if (e->text == NULL) errx(1, "event_add: cannot allocate memory"); e->extra = NULL; if (extra != NULL && extra[0] != '\0') e->extra = strdup(extra); addtodate(e, year, month, day); return (e); } void event_continue(struct event *e, char *txt) { char *text; /* * Adding text to the event: * - Save a copy of the old text (unknown length, so strdup()) * - Allocate enough space for old text + \n + new text + 0 * - Store the old text + \n + new text * - Destroy the saved copy. */ text = strdup(e->text); if (text == NULL) errx(1, "event_continue: cannot allocate memory"); free(e->text); e->text = (char *)malloc(strlen(text) + strlen(txt) + 3); if (e->text == NULL) errx(1, "event_continue: cannot allocate memory"); strcpy(e->text, text); strcat(e->text, "\n"); strcat(e->text, txt); free(text); return; } void event_print_all(FILE *fp) { struct event *e; while (walkthrough_dates(&e) != 0) { #ifdef DEBUG fprintf(stderr, "event_print_allmonth: %d, day: %d\n", month, day); #endif /* * Go through all events and print the text of the matching * dates */ while (e != NULL) { (void)fprintf(fp, "%s%c%s%s%s%s\n", e->date, e->var ? '*' : ' ', e->text, e->extra != NULL ? " (" : "", e->extra != NULL ? e->extra : "", e->extra != NULL ? ")" : "" ); e = e->next; } } } Property changes on: user/edwin/calendar/events.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: user/edwin/calendar/locale.c =================================================================== --- user/edwin/calendar/locale.c (revision 204262) +++ user/edwin/calendar/locale.c (revision 204263) Property changes on: user/edwin/calendar/locale.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: user/edwin/calendar/parsedata.c =================================================================== --- user/edwin/calendar/parsedata.c (revision 204262) +++ user/edwin/calendar/parsedata.c (revision 204263) @@ -1,1017 +1,1017 @@ /*- * Copyright (c) 1992-2009 Edwin Groothuis. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include -__FBSDID("$FreeBSD: user/edwin/calendar/day.c 200813 2009-12-21 21:17:59Z edwin $"); +__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include "calendar.h" static char *showflags(int flags); static int isonlydigits(char *s, int star); static char *getmonthname(int i); static int checkmonth(char *s, int *len, int *offset, char **month); static char *getdayofweekname(int i); static int checkdayofweek(char *s, int *len, int *offset, char **dow); static int isonlydigits(char *s, int nostar); static int indextooffset(char *s); static int parseoffset(char *s); static char *floattoday(int year, double f); static char *floattotime(double f); /* * Expected styles: * * Date ::= Month . ' ' . DayOfMonth | * Month . ' ' . DayOfWeek . ModifierIndex | * Month . '/' . DayOfMonth | * Month . '/' . DayOfWeek . ModifierIndex | * DayOfMonth . ' ' . Month | * DayOfMonth . '/' . Month | * DayOfWeek . ModifierIndex . ' ' .Month | * DayOfWeek . ModifierIndex . '/' .Month | * DayOfWeek . ModifierIndex | * SpecialDay . ModifierOffset * * Month ::= MonthName | MonthNumber | '*' * MonthNumber ::= '0' ... '9' | '00' ... '09' | '10' ... '12' * MonthName ::= MonthNameShort | MonthNameLong * MonthNameLong ::= 'January' ... 'December' * MonthNameShort ::= 'Jan' ... 'Dec' | 'Jan.' ... 'Dec.' * * DayOfWeek ::= DayOfWeekShort | DayOfWeekLong * DayOfWeekShort ::= 'Mon' .. 'Sun' * DayOfWeekLong ::= 'Monday' .. 'Sunday' * DayOfMonth ::= '0' ... '9' | '00' ... '09' | '10' ... '29' | * '30' ... '31' | '*' * * ModifierOffset ::= '' | '+' . ModifierNumber | '-' . ModifierNumber * ModifierNumber ::= '0' ... '9' | '00' ... '99' | '000' ... '299' | * '300' ... '359' | '360' ... '365' * ModifierIndex ::= 'Second' | 'Third' | 'Fourth' | 'Fifth' | * 'First' | 'Last' * * SpecialDay ::= 'Easter' | 'Pashka' | 'ChineseNewYear' * */ static int determinestyle(char *date, int *flags, char *month, int *imonth, char *dayofmonth, int *idayofmonth, char *dayofweek, int *idayofweek, char *modifieroffset, char *modifierindex, char *specialday) { char *p, *dow, *pmonth, *p1, *p2; char pold; int len, offset; *flags = F_NONE; *month = '\0'; *imonth = 0; *dayofmonth = '\0'; *idayofmonth = 0; *dayofweek = '\0'; *idayofweek = 0; *modifieroffset = '\0'; *modifierindex = '\0'; *specialday = '\0'; #define CHECKSPECIAL(s1, s2, lens2, type) \ if (s2 != NULL && strncmp(s1, s2, lens2) == 0) { \ *flags |= F_SPECIALDAY; \ *flags |= type; \ *flags |= F_VARIABLE; \ if (strlen(s1) == lens2) { \ strcpy(specialday, s1); \ return (1); \ } \ strncpy(specialday, s1, lens2); \ specialday[lens2] = '\0'; \ strcpy(modifieroffset, s1 + lens2); \ *flags |= F_MODIFIEROFFSET; \ return (1); \ } if ((p = strchr(date, ' ')) == NULL) { if ((p = strchr(date, '/')) == NULL) { CHECKSPECIAL(date, STRING_CNY, strlen(STRING_CNY), F_CNY); CHECKSPECIAL(date, ncny.name, ncny.len, F_CNY); CHECKSPECIAL(date, STRING_NEWMOON, strlen(STRING_NEWMOON), F_NEWMOON); CHECKSPECIAL(date, nnewmoon.name, nnewmoon.len, F_NEWMOON); CHECKSPECIAL(date, STRING_FULLMOON, strlen(STRING_FULLMOON), F_FULLMOON); CHECKSPECIAL(date, nfullmoon.name, nfullmoon.len, F_FULLMOON); CHECKSPECIAL(date, STRING_PASKHA, strlen(STRING_PASKHA), F_PASKHA); CHECKSPECIAL(date, npaskha.name, npaskha.len, F_PASKHA); CHECKSPECIAL(date, STRING_EASTER, strlen(STRING_EASTER), F_EASTER); CHECKSPECIAL(date, neaster.name, neaster.len, F_EASTER); CHECKSPECIAL(date, STRING_MAREQUINOX, strlen(STRING_MAREQUINOX), F_MAREQUINOX); CHECKSPECIAL(date, nmarequinox.name, nmarequinox.len, F_SEPEQUINOX); CHECKSPECIAL(date, STRING_SEPEQUINOX, strlen(STRING_SEPEQUINOX), F_SEPEQUINOX); CHECKSPECIAL(date, nsepequinox.name, nsepequinox.len, F_SEPEQUINOX); CHECKSPECIAL(date, STRING_JUNSOLSTICE, strlen(STRING_JUNSOLSTICE), F_JUNSOLSTICE); CHECKSPECIAL(date, njunsolstice.name, njunsolstice.len, F_JUNSOLSTICE); CHECKSPECIAL(date, STRING_DECSOLSTICE, strlen(STRING_DECSOLSTICE), F_DECSOLSTICE); CHECKSPECIAL(date, ndecsolstice.name, ndecsolstice.len, F_DECSOLSTICE); if (checkdayofweek(date, &len, &offset, &dow) != 0) { *flags |= F_DAYOFWEEK; *flags |= F_VARIABLE; *idayofweek = offset; if (strlen(date) == len) { strcpy(dayofweek, date); return (1); } strncpy(dayofweek, date, len); dayofweek[len] = '\0'; strcpy(modifierindex, date + len); *flags |= F_MODIFIERINDEX; return (1); } if (isonlydigits(date, 1)) { /* Assume month number only */ *flags |= F_MONTH; *imonth = (int)strtol(date, (char **)NULL, 10); strcpy(month, getmonthname(*imonth)); return(1); } return (0); } } /* * AFTER this, leave by goto-ing to "allfine" or "fail" to restore the * original data in `date'. */ pold = *p; *p = 0; p1 = date; p2 = p + 1; /* Now p2 points to the next field and p1 to the first field */ /* Check if there is a month-string in the date */ if ((checkmonth(p1, &len, &offset, &pmonth) != 0) || (checkmonth(p2, &len, &offset, &pmonth) != 0 && (p2 = p1))) { /* p2 is the non-month part */ *flags |= F_MONTH; *imonth = offset; strcpy(month, getmonthname(offset)); if (isonlydigits(p2, 1)) { strcpy(dayofmonth, p2); *idayofmonth = (int)strtol(p2, (char **)NULL, 10); *flags |= F_DAYOFMONTH; goto allfine; } if (strcmp(p2, "*") == 0) { *flags |= F_ALLDAY; goto allfine; } if (checkdayofweek(p2, &len, &offset, &dow) != 0) { *flags |= F_DAYOFWEEK; *flags |= F_VARIABLE; *idayofweek = offset; strcpy(dayofweek, getdayofweekname(offset)); if (strlen(p2) == len) goto allfine; strcpy(modifierindex, p2 + len); *flags |= F_MODIFIERINDEX; goto allfine; } goto fail; } /* Check if there is an every-day or every-month in the string */ if ((strcmp(p1, "*") == 0 && isonlydigits(p2, 1)) || (strcmp(p2, "*") == 0 && isonlydigits(p1, 1) && (p2 = p1))) { int d; *flags |= F_ALLMONTH; *flags |= F_DAYOFMONTH; d = (int)strtol(p2, (char **)NULL, 10); *idayofmonth = d; sprintf(dayofmonth, "%d", d); goto allfine; } /* Month as a number, then a weekday */ if (isonlydigits(p1, 1) && checkdayofweek(p2, &len, &offset, &dow) != 0) { int d; *flags |= F_MONTH; *flags |= F_DAYOFWEEK; *flags |= F_VARIABLE; *idayofweek = offset; d = (int)strtol(p1, (char **)NULL, 10); *imonth = d; strcpy(month, getmonthname(d)); strcpy(dayofweek, getdayofweekname(offset)); if (strlen(p2) == len) goto allfine; strcpy(modifierindex, p2 + len); *flags |= F_MODIFIERINDEX; goto allfine; } /* If both the month and date are specified as numbers */ if (isonlydigits(p1, 1) && isonlydigits(p2, 0)) { /* Now who wants to be this ambigious? :-( */ int m, d; if (strchr(p2, '*') != NULL) *flags |= F_VARIABLE; m = (int)strtol(p1, (char **)NULL, 10); d = (int)strtol(p2, (char **)NULL, 10); *flags |= F_MONTH; *flags |= F_DAYOFMONTH; if (m > 12) { *imonth = d; *idayofmonth = m; strcpy(month, getmonthname(d)); sprintf(dayofmonth, "%d", m); } else { *imonth = m; *idayofmonth = d; strcpy(month, getmonthname(m)); sprintf(dayofmonth, "%d", d); } goto allfine; } /* FALLTHROUGH */ fail: *p = pold; return (0); allfine: *p = pold; return (1); } static void remember(int *index, int *y, int *m, int *d, char **ed, int yy, int mm, int dd, char *extra) { static int warned = 0; if (*index >= MAXCOUNT - 1) { if (warned == 0) warnx("Index > %d, ignored", MAXCOUNT); warned++; return; } y[*index] = yy; m[*index] = mm; d[*index] = dd; if (extra != NULL) strcpy(ed[*index], extra); else ed[*index][0] = '\0'; *index += 1; } static void debug_determinestyle(int dateonly, char *date, int flags, char *month, int imonth, char *dayofmonth, int idayofmonth, char *dayofweek, int idayofweek, char *modifieroffset, char *modifierindex, char *specialday) { if (dateonly != 0) { printf("-------\ndate: |%s|\n", date); if (dateonly == 1) return; } printf("flags: %x - %s\n", flags, showflags(flags)); if (modifieroffset[0] != '\0') printf("modifieroffset: |%s|\n", modifieroffset); if (modifierindex[0] != '\0') printf("modifierindex: |%s|\n", modifierindex); if (month[0] != '\0') printf("month: |%s| (%d)\n", month, imonth); if (dayofmonth[0] != '\0') printf("dayofmonth: |%s| (%d)\n", dayofmonth, idayofmonth); if (dayofweek[0] != '\0') printf("dayofweek: |%s| (%d)\n", dayofweek, idayofweek); if (specialday[0] != '\0') printf("specialday: |%s|\n", specialday); } struct yearinfo { int year; int ieaster, ipaskha, firstcnyday; double ffullmoon[MAXMOONS], fnewmoon[MAXMOONS]; double ffullmooncny[MAXMOONS], fnewmooncny[MAXMOONS]; int ichinesemonths[MAXMOONS]; double equinoxdays[2], solsticedays[2]; int *mondays; struct yearinfo *next; }; /* * Possible date formats include any combination of: * 3-charmonth (January, Jan, Jan) * 3-charweekday (Friday, Monday, mon.) * numeric month or day (1, 2, 04) * * Any character may separate them, or they may not be separated. Any line, * following a line that is matched, that starts with "whitespace", is shown * along with the matched line. */ int parsedaymonth(char *date, int *yearp, int *monthp, int *dayp, int *flags, char **edp) { char month[100], dayofmonth[100], dayofweek[100], modifieroffset[100]; char modifierindex[100], specialday[100]; int idayofweek, imonth, idayofmonth, year, index; int d, m, dow, rm, rd, offset; char *ed; int retvalsign = 1; static struct yearinfo *years, *yearinfo; /* * CONVENTION * * Month: 1-12 * Monthname: Jan .. Dec * Day: 1-31 * Weekday: Mon .. Sun * */ *flags = 0; if (debug) debug_determinestyle(1, date, *flags, month, imonth, dayofmonth, idayofmonth, dayofweek, idayofweek, modifieroffset, modifierindex, specialday); if (determinestyle(date, flags, month, &imonth, dayofmonth, &idayofmonth, dayofweek, &idayofweek, modifieroffset, modifierindex, specialday) == 0) { if (debug) printf("Failed!\n"); return (0); } if (debug) debug_determinestyle(0, date, *flags, month, imonth, dayofmonth, idayofmonth, dayofweek, idayofweek, modifieroffset, modifierindex, specialday); index = 0; for (year = year1; year <= year2; year++) { /* Get important dates for this year */ yearinfo = years; while (yearinfo != NULL) { if (yearinfo->year == year) break; yearinfo = yearinfo -> next; } if (yearinfo == NULL) { yearinfo = (struct yearinfo *)calloc(1, sizeof(struct yearinfo)); if (yearinfo == NULL) errx(1, "Unable to allocate more years"); yearinfo->year = year; yearinfo->next = years; years = yearinfo; yearinfo->mondays = mondaytab[isleap(year)]; yearinfo->ieaster = easter(year); fpom(year, UTCoffset, yearinfo->ffullmoon, yearinfo->fnewmoon); fpom(year, UTCOFFSET_CNY, yearinfo->ffullmooncny, yearinfo->fnewmooncny); fequinoxsolstice(year, UTCoffset, yearinfo->equinoxdays, yearinfo->solsticedays); /* * CNY: Match day with sun longitude at 330` with new * moon */ yearinfo->firstcnyday = calculatesunlongitude30(year, UTCOFFSET_CNY, yearinfo->ichinesemonths); for (m = 0; yearinfo->fnewmooncny[m] >= 0; m++) { if (yearinfo->fnewmooncny[m] > yearinfo->firstcnyday) { yearinfo->firstcnyday = floor(yearinfo->fnewmooncny[m - 1]); break; } } } /* Same day every year */ if (*flags == (F_MONTH | F_DAYOFMONTH)) { if (!remember_ymd(year, imonth, idayofmonth)) continue; remember(&index, yearp, monthp, dayp, edp, year, imonth, idayofmonth, NULL); continue; } /* XXX Same day every year, but variable */ if (*flags == (F_MONTH | F_DAYOFMONTH | F_VARIABLE)) { if (!remember_ymd(year, imonth, idayofmonth)) continue; remember(&index, yearp, monthp, dayp, edp, year, imonth, idayofmonth, NULL); continue; } /* Same day every month */ if (*flags == (F_ALLMONTH | F_DAYOFMONTH)) { for (m = 1; m <= 12; m++) { if (!remember_ymd(year, m, idayofmonth)) continue; remember(&index, yearp, monthp, dayp, edp, year, m, idayofmonth, NULL); } continue; } /* Every day of a month */ if (*flags == (F_ALLDAY | F_MONTH)) { for (d = 1; d <= yearinfo->mondays[imonth]; d++) { if (!remember_ymd(year, imonth, d)) continue; remember(&index, yearp, monthp, dayp, edp, year, imonth, d, NULL); } continue; } /* One day of every month */ if (*flags == (F_ALLMONTH | F_DAYOFWEEK)) { for (m = 1; m <= 12; m++) { if (!remember_ymd(year, m, idayofmonth)) continue; remember(&index, yearp, monthp, dayp, edp, year, m, idayofmonth, NULL); } continue; } /* Every dayofweek of the year */ if (*flags == (F_DAYOFWEEK | F_VARIABLE)) { dow = first_dayofweek_of_year(year); d = (idayofweek - dow + 8) % 7; while (d <= 366) { if (remember_yd(year, d, &rm, &rd)) remember(&index, yearp, monthp, dayp, edp, year, rm, rd, NULL); d += 7; } continue; } /* A certain dayofweek of a month */ if (*flags == (F_MONTH | F_DAYOFWEEK | F_MODIFIERINDEX | F_VARIABLE)) { offset = indextooffset(modifierindex); dow = first_dayofweek_of_month(year, imonth); d = (idayofweek - dow + 8) % 7; if (offset > 0) { while (d <= yearinfo->mondays[imonth]) { if (--offset == 0 && remember_ymd(year, imonth, d)) { remember(&index, yearp, monthp, dayp, edp, year, imonth, d, NULL); continue; } d += 7; } continue; } if (offset < 0) { while (d <= yearinfo->mondays[imonth]) d += 7; while (offset != 0) { offset++; d -= 7; } if (remember_ymd(year, imonth, d)) remember(&index, yearp, monthp, dayp, edp, year, imonth, d, NULL); continue; } continue; } /* Every dayofweek of the month */ if (*flags == (F_DAYOFWEEK | F_MONTH | F_VARIABLE)) { dow = first_dayofweek_of_month(year, imonth); d = (idayofweek - dow + 8) % 7; while (d <= yearinfo->mondays[imonth]) { if (remember_ymd(year, imonth, d)) remember(&index, yearp, monthp, dayp, edp, year, imonth, d, NULL); d += 7; } continue; } /* Easter */ if ((*flags & ~F_MODIFIEROFFSET) == (F_SPECIALDAY | F_VARIABLE | F_EASTER)) { offset = 0; if ((*flags & F_MODIFIEROFFSET) != 0) offset = parseoffset(modifieroffset); if (remember_yd(year, yearinfo->ieaster + offset, &rm, &rd)) remember(&index, yearp, monthp, dayp, edp, year, rm, rd, NULL); continue; } /* Paskha */ if ((*flags & ~F_MODIFIEROFFSET) == (F_SPECIALDAY | F_VARIABLE | F_PASKHA)) { offset = 0; if ((*flags & F_MODIFIEROFFSET) != 0) offset = parseoffset(modifieroffset); if (remember_yd(year, yearinfo->ipaskha + offset, &rm, &rd)) remember(&index, yearp, monthp, dayp, edp, year, rm, rd, NULL); continue; } /* Chinese New Year */ if ((*flags & ~F_MODIFIEROFFSET) == (F_SPECIALDAY | F_VARIABLE | F_CNY)) { offset = 0; if ((*flags & F_MODIFIEROFFSET) != 0) offset = parseoffset(modifieroffset); if (remember_yd(year, yearinfo->firstcnyday + offset, &rm, &rd)) remember(&index, yearp, monthp, dayp, edp, year, rm, rd, NULL); continue; } /* FullMoon */ if ((*flags & ~F_MODIFIEROFFSET) == (F_SPECIALDAY | F_VARIABLE | F_FULLMOON)) { int i; offset = 0; if ((*flags & F_MODIFIEROFFSET) != 0) offset = parseoffset(modifieroffset); for (i = 0; yearinfo->ffullmoon[i] > 0; i++) { if (remember_yd(year, floor(yearinfo->ffullmoon[i]) + offset, &rm, &rd)) { ed = floattotime( yearinfo->ffullmoon[i]); remember(&index, yearp, monthp, dayp, edp, year, rm, rd, ed); } } continue; } /* NewMoon */ if ((*flags & ~F_MODIFIEROFFSET) == (F_SPECIALDAY | F_VARIABLE | F_NEWMOON)) { int i; offset = 0; if ((*flags & F_MODIFIEROFFSET) != 0) offset = parseoffset(modifieroffset); for (i = 0; yearinfo->ffullmoon[i] > 0; i++) { if (remember_yd(year, floor(yearinfo->fnewmoon[i]) + offset, &rm, &rd)) { ed = floattotime(yearinfo->fnewmoon[i]); remember(&index, yearp, monthp, dayp, edp, year, rm, rd, ed); } } continue; } /* (Mar|Sep)Equinox */ if ((*flags & ~F_MODIFIEROFFSET) == (F_SPECIALDAY | F_VARIABLE | F_MAREQUINOX)) { offset = 0; if ((*flags & F_MODIFIEROFFSET) != 0) offset = parseoffset(modifieroffset); if (remember_yd(year, yearinfo->equinoxdays[0] + offset, &rm, &rd)) { ed = floattotime(yearinfo->equinoxdays[0]); remember(&index, yearp, monthp, dayp, edp, year, rm, rd, ed); } continue; } if ((*flags & ~F_MODIFIEROFFSET) == (F_SPECIALDAY | F_VARIABLE | F_SEPEQUINOX)) { offset = 0; if ((*flags & F_MODIFIEROFFSET) != 0) offset = parseoffset(modifieroffset); if (remember_yd(year, yearinfo->equinoxdays[1] + offset, &rm, &rd)) { ed = floattotime(yearinfo->equinoxdays[1]); remember(&index, yearp, monthp, dayp, edp, year, rm, rd, ed); } continue; } /* (Jun|Dec)Solstice */ if ((*flags & ~F_MODIFIEROFFSET) == (F_SPECIALDAY | F_VARIABLE | F_JUNSOLSTICE)) { offset = 0; if ((*flags & F_MODIFIEROFFSET) != 0) offset = parseoffset(modifieroffset); if (remember_yd(year, yearinfo->solsticedays[0] + offset, &rm, &rd)) { ed = floattotime(yearinfo->solsticedays[0]); remember(&index, yearp, monthp, dayp, edp, year, rm, rd, ed); } continue; } if ((*flags & ~F_MODIFIEROFFSET) == (F_SPECIALDAY | F_VARIABLE | F_DECSOLSTICE)) { offset = 0; if ((*flags & F_MODIFIEROFFSET) != 0) offset = parseoffset(modifieroffset); if (remember_yd(year, yearinfo->solsticedays[1] + offset, &rm, &rd)) { ed = floattotime(yearinfo->solsticedays[1]); remember(&index, yearp, monthp, dayp, edp, year, rm, rd, ed); } continue; } printf("Unprocessed:\n"); debug_determinestyle(2, date, *flags, month, imonth, dayofmonth, idayofmonth, dayofweek, idayofweek, modifieroffset, modifierindex, specialday); retvalsign = -1; } if (retvalsign == -1) return (-index - 1); else return (index); } static char * showflags(int flags) { static char s[1000]; s[0] = '\0'; if ((flags & F_MONTH) != 0) strcat(s, "month "); if ((flags & F_DAYOFWEEK) != 0) strcat(s, "dayofweek "); if ((flags & F_DAYOFMONTH) != 0) strcat(s, "dayofmonth "); if ((flags & F_MODIFIERINDEX) != 0) strcat(s, "modifierindex "); if ((flags & F_MODIFIEROFFSET) != 0) strcat(s, "modifieroffset "); if ((flags & F_SPECIALDAY) != 0) strcat(s, "specialday "); if ((flags & F_ALLMONTH) != 0) strcat(s, "allmonth "); if ((flags & F_ALLDAY) != 0) strcat(s, "allday "); if ((flags & F_VARIABLE) != 0) strcat(s, "variable "); if ((flags & F_CNY) != 0) strcat(s, "chinesenewyear "); if ((flags & F_PASKHA) != 0) strcat(s, "paskha "); if ((flags & F_EASTER) != 0) strcat(s, "easter "); if ((flags & F_FULLMOON) != 0) strcat(s, "fullmoon "); if ((flags & F_NEWMOON) != 0) strcat(s, "newmoon "); if ((flags & F_MAREQUINOX) != 0) strcat(s, "marequinox "); if ((flags & F_SEPEQUINOX) != 0) strcat(s, "sepequinox "); if ((flags & F_JUNSOLSTICE) != 0) strcat(s, "junsolstice "); if ((flags & F_DECSOLSTICE) != 0) strcat(s, "decsolstice "); return s; } static char * getmonthname(int i) { if (nmonths[i - 1].len != 0 && nmonths[i - 1].name != NULL) return (nmonths[i - 1].name); return ((char *)months[i - 1]); } static int checkmonth(char *s, int *len, int *offset, char **month) { struct fixs *n; int i; for (i = 0; fnmonths[i].name != NULL; i++) { n = fnmonths + i; if (strncasecmp(s, n->name, n->len) == 0) { *len = n->len; *month = n->name; *offset = i + 1; return (1); } } for (i = 0; nmonths[i].name != NULL; i++) { n = nmonths + i; if (strncasecmp(s, n->name, n->len) == 0) { *len = n->len; *month = n->name; *offset = i + 1; return (1); } } for (i = 0; fmonths[i] != NULL; i++) { *len = strlen(fmonths[i]); if (strncasecmp(s, fmonths[i], *len) == 0) { *month = (char *)fmonths[i]; *offset = i + 1; return (1); } } for (i = 0; months[i] != NULL; i++) { if (strncasecmp(s, months[i], 3) == 0) { *len = 3; *month = (char *)months[i]; *offset = i + 1; return (1); } } return (0); } static char * getdayofweekname(int i) { if (ndays[i].len != 0 && ndays[i].name != NULL) return (ndays[i].name); return ((char *)days[i]); } static int checkdayofweek(char *s, int *len, int *offset, char **dow) { struct fixs *n; int i; for (i = 0; fndays[i].name != NULL; i++) { n = fndays + i; if (strncasecmp(s, n->name, n->len) == 0) { *len = n->len; *dow = n->name; *offset = i; return (1); } } for (i = 0; ndays[i].name != NULL; i++) { n = ndays + i; if (strncasecmp(s, n->name, n->len) == 0) { *len = n->len; *dow = n->name; *offset = i; return (1); } } for (i = 0; fdays[i] != NULL; i++) { *len = strlen(fdays[i]); if (strncasecmp(s, fdays[i], *len) == 0) { *dow = (char *)fdays[i]; *offset = i; return (1); } } for (i = 0; days[i] != NULL; i++) { if (strncasecmp(s, days[i], 3) == 0) { *len = 3; *dow = (char *)days[i]; *offset = i; return (1); } } return (0); } static int isonlydigits(char *s, int nostar) { int i; for (i = 0; s[i] != '\0'; i++) { if (nostar == 0 && s[i] == '*' && s[i + 1] == '\0') return 1; if (!isdigit(s[i])) return (0); } return (1); } static int indextooffset(char *s) { if (strcasecmp(s, "first") == 0) return (1); if (strcasecmp(s, "second") == 0) return (2); if (strcasecmp(s, "third") == 0) return (3); if (strcasecmp(s, "fourth") == 0) return (4); if (strcasecmp(s, "fifth") == 0) return (5); if (strcasecmp(s, "last") == 0) return (-1); return (0); } static int parseoffset(char *s) { return strtol(s, NULL, 10); } static char * floattotime(double f) { static char buf[100]; int hh, mm, ss, i; f -= floor(f); i = f * SECSPERDAY; hh = i / SECSPERHOUR; i %= SECSPERHOUR; mm = i / SECSPERMINUTE; i %= SECSPERMINUTE; ss = i; sprintf(buf, "%02d:%02d:%02d", hh, mm, ss); return (buf); } static char * floattoday(int year, double f) { static char buf[100]; int i, m, d, hh, mm, ss; int *cumdays = cumdaytab[isleap(year)]; for (i = 0; 1 + cumdays[i] < f; i++) ;; m = --i; d = floor(f - 1 - cumdays[i]); f -= floor(f); i = f * SECSPERDAY; hh = i / SECSPERHOUR; i %= SECSPERHOUR; mm = i / SECSPERMINUTE; i %= SECSPERMINUTE; ss = i; sprintf(buf, "%02d-%02d %02d:%02d:%02d", m, d, hh, mm, ss); return (buf); } char * inttoday(int year, int f) { static char buf[100]; int i, m, d; int *cumdays = cumdaytab[isleap(year)]; for (i = 0; 1 + cumdays[i] < f; i++) ;; m = --i; d = floor(f - 1 - cumdays[i]); f -= floor(f); sprintf(buf, "%02d-%02d", m, d); return (buf); } void dodebug(char *what) { int year; printf("UTCOffset: %g\n", UTCoffset); printf("eastlongitude: %d\n", eastlongitude); if (strcmp(what, "moon") == 0) { double ffullmoon[MAXMOONS], fnewmoon[MAXMOONS]; int i; for (year = year1; year <= year2; year++) { fpom(year, UTCoffset, ffullmoon, fnewmoon); printf("Full moon %d:\t", year); for (i = 0; ffullmoon[i] >= 0; i++) { printf("%g (%s) ", ffullmoon[i], floattoday(year, ffullmoon[i])); } printf("\nNew moon %d:\t", year); for (i = 0; fnewmoon[i] >= 0; i++) { printf("%g (%s) ", fnewmoon[i], floattoday(year, fnewmoon[i])); } printf("\n"); } return; } if (strcmp(what, "sun") == 0) { double equinoxdays[2], solsticedays[2]; for (year = year1; year <= year2; year++) { printf("Sun in %d:\n", year); fequinoxsolstice(year, UTCoffset, equinoxdays, solsticedays); printf("e[0] - %g (%s)\n", equinoxdays[0], floattoday(year, equinoxdays[0])); printf("e[1] - %g (%s)\n", equinoxdays[1], floattoday(year, equinoxdays[1])); printf("s[0] - %g (%s)\n", solsticedays[0], floattoday(year, solsticedays[0])); printf("s[1] - %g (%s)\n", solsticedays[1], floattoday(year, solsticedays[1])); } return; } } Property changes on: user/edwin/calendar/parsedata.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: user/edwin/calendar/pom.c =================================================================== --- user/edwin/calendar/pom.c (revision 204262) +++ user/edwin/calendar/pom.c (revision 204263) @@ -1,279 +1,279 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software posted to USENET. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static const char sccsid[] = "@(#)pom.c 8.1 (Berkeley) 5/31/93"; #endif /* not lint */ #endif #include -__FBSDID("$FreeBSD: head/games/pom/pom.c 201613 2010-01-05 21:14:48Z edwin $"); +__FBSDID("$FreeBSD$"); /* * 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 #include #include #include #include #include #include #include "calendar.h" #ifndef PI #define PI 3.14159265358979323846 #endif #define EPOCH 85 #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 */ #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) static void adj360(double *); static double dtor(double); static double potm(double); static double potm_minute(double days, int olddir); void pom(int year, double utcoffset, int *fms, int *nms) { double ffms[MAXMOONS]; double fnms[MAXMOONS]; int i, j; fpom(year, utcoffset, ffms, fnms); for (i = 0; ffms[i] != 0; i++) fms[j++] = round(ffms[i]); fms[i] = -1; for (i = 0; fnms[i] != 0; i++) nms[i] = round(fnms[i]); nms[i] = -1; } void fpom(int year, double utcoffset, double *ffms, double *fnms) { time_t tt; struct tm GMT, tmd_today, tmd_tomorrow; double days_today, days_tomorrow, today, tomorrow; int cnt, d; int yeardays; int olddir, newdir; double *pfnms, *pffms, t; pfnms = fnms; pffms = ffms; /* * We take the phase of the moon one second before and one second * after midnight. */ memset(&tmd_today, 0, sizeof(tmd_today)); tmd_today.tm_year = year - 1900; tmd_today.tm_mon = 0; tmd_today.tm_mday = -1; /* 31 December */ tmd_today.tm_hour = 23; tmd_today.tm_min = 59; tmd_today.tm_sec = 59; memset(&tmd_tomorrow, 0, sizeof(tmd_tomorrow)); tmd_tomorrow.tm_year = year - 1900; tmd_tomorrow.tm_mon = 0; tmd_tomorrow.tm_mday = 0; /* 01 January */ tmd_tomorrow.tm_hour = 0; tmd_tomorrow.tm_min = 0; tmd_tomorrow.tm_sec = 1; tt = mktime(&tmd_today); gmtime_r(&tt, &GMT); yeardays = 0; for (cnt = EPOCH; cnt < GMT.tm_year; ++cnt) yeardays += isleap(1900 + cnt) ? DAYSPERLEAPYEAR : DAYSPERYEAR; days_today = (GMT.tm_yday + 1) + ((GMT.tm_hour + (GMT.tm_min / FSECSPERMINUTE) + (GMT.tm_sec / FSECSPERHOUR)) / FHOURSPERDAY); days_today += yeardays; tt = mktime(&tmd_tomorrow); gmtime_r(&tt, &GMT); yeardays = 0; for (cnt = EPOCH; cnt < GMT.tm_year; ++cnt) yeardays += isleap(1900 + cnt) ? DAYSPERLEAPYEAR : DAYSPERYEAR; days_tomorrow = (GMT.tm_yday + 1) + ((GMT.tm_hour + (GMT.tm_min / FSECSPERMINUTE) + (GMT.tm_sec / FSECSPERHOUR)) / FHOURSPERDAY); days_tomorrow += yeardays; today = potm(days_today); /* 30 December 23:59:59 */ tomorrow = potm(days_tomorrow); /* 31 December 00:00:01 */ olddir = today > tomorrow ? -1 : +1; yeardays = 1 + isleap(year) ? DAYSPERLEAPYEAR : DAYSPERYEAR; /* reuse */ for (d = 0; d <= yeardays; d++) { today = potm(days_today); tomorrow = potm(days_tomorrow); newdir = today > tomorrow ? -1 : +1; if (olddir != newdir) { t = potm_minute(days_today - 1, olddir) + utcoffset / FHOURSPERDAY; if (olddir == -1 && newdir == +1) { *pfnms = d - 1 + t; pfnms++; } else if (olddir == +1 && newdir == -1) { *pffms = d - 1 + t; pffms++; } } olddir = newdir; days_today++; days_tomorrow++; } *pffms = -1; *pfnms = -1; } static double potm_minute(double days, int olddir) { double period = FSECSPERDAY / 2.0; double p1, p2; double before, after; int newdir; // printf("---> days:%g olddir:%d\n", days, olddir); p1 = days + (period / SECSPERDAY); period /= 2; while (period > 30) { /* half a minute */ // printf("period:%g - p1:%g - ", period, p1); p2 = p1 + (2.0 / SECSPERDAY); before = potm(p1); after = potm(p2); // printf("before:%10.10g - after:%10.10g\n", before, after); newdir = before < after ? -1 : +1; if (olddir != newdir) p1 += (period / SECSPERDAY); else p1 -= (period / SECSPERDAY); period /= 2; // printf("newdir:%d - p1:%10.10f - period:%g\n", // newdir, p1, period); } p1 -= floor(p1); //exit(0); return (p1); } /* * potm -- * return phase of the moon, as a percentage [0 ... 100] */ static double potm(double 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 */ adj360(&N); Msol = N + EPSILONg - RHOg; /* sec 42 #4 */ adj360(&Msol); Ec = 360 / PI * ECCEN * 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 */ } /* * dtor -- * convert degrees to radians */ static double dtor(double deg) { return(deg * PI / 180); } /* * adj360 -- * adjust value so 0 <= deg <= 360 */ static void adj360(double *deg) { for (;;) if (*deg < 0) *deg += 360; else if (*deg > 360) *deg -= 360; else break; } Property changes on: user/edwin/calendar/pom.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: user/edwin/calendar/sunpos.c =================================================================== --- user/edwin/calendar/sunpos.c (revision 204262) +++ user/edwin/calendar/sunpos.c (revision 204263) @@ -1,438 +1,443 @@ /*- * Copyright (c) 2009-2010 Edwin Groothuis. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* * This code is created to match the formulas available at: * Formula and examples obtained from "How to Calculate alt/az: SAAO" at * http://www.saao.ac.za/public-info/sun-moon-stars/sun-index/how-to-calculate-altaz/ */ #include #include #include #include #include #include #include "calendar.h" #define D2R(m) ((m) / 180 * M_PI) #define R2D(m) ((m) * 180 / M_PI) #define SIN(x) (sin(D2R(x))) #define COS(x) (cos(D2R(x))) #define TAN(x) (tan(D2R(x))) #define ASIN(x) (R2D(asin(x))) #define ATAN(x) (R2D(atan(x))) #ifdef NOTDEF static void comp(char *s, double v, double c) { printf("%-*s %*g %*g %*g\n", 15, s, 15, v, 15, c, 15, v - c); } int expY; double expZJ = 30.5; double expUTHM = 8.5; double expD = 34743.854; double expT = 0.9512349; double expL = 324.885; double expM = 42.029; double expepsilon = 23.4396; double explambda = 326.186; double expalpha = 328.428; double expDEC = -12.789; double expeastlongitude = 17.10; double explatitude = -22.57; double expHA = -37.673; double expALT = 49.822; double expAZ = 67.49; #endif static double fixup(double *d) { if (*d < 0) { while (*d < 0) *d += 360; } else { while (*d > 360) *d -= 360; } return (*d); } static double ZJtable[] = { 0, -0.5, 30.5, 58.5, 89.5, 119.5, 150.5, 180.5, 211.5, 242.5, 272.5, 303.5, 333.5 }; static void sunpos(int inYY, int inMM, int inDD, double UTCOFFSET, int inHOUR, int inMIN, - double eastlongitude, double latitude, double *L, double *DEC) + int inSEC, double eastlongitude, double latitude, double *L, double *DEC) { int Y; double ZJ, D, T, M, epsilon, lambda, alpha, HA, UTHM; ZJ = ZJtable[inMM]; if (inMM <= 2 && isleap(inYY)) ZJ -= 1.0; - UTHM = inHOUR + inMIN / FSECSPERMINUTE + UTCOFFSET; + UTHM = inHOUR + inMIN / FMINSPERHOUR + inSEC / FSECSPERHOUR + UTCOFFSET; Y = inYY - 1900; /* 1 */ D = floor(365.25 * Y) + ZJ + inDD + UTHM / FHOURSPERDAY; /* 3 */ T = D / 36525.0; /* 4 */ *L = 279.697 + 36000.769 * T; /* 5 */ fixup(L); M = 358.476 + 35999.050 * T; /* 6 */ fixup(&M); epsilon = 23.452 - 0.013 * T; /* 7 */ fixup(&epsilon); lambda = *L + (1.919 - 0.005 * T) * SIN(M) + 0.020 * SIN(2 * M);/* 8 */ fixup(&lambda); alpha = ATAN(TAN(lambda) * COS(epsilon)); /* 9 */ /* Alpha should be in the same quadrant as lamba */ { int lssign = sin(D2R(lambda)) < 0 ? -1 : 1; int lcsign = cos(D2R(lambda)) < 0 ? -1 : 1; while (((sin(D2R(alpha)) < 0) ? -1 : 1) != lssign || ((cos(D2R(alpha)) < 0) ? -1 : 1) != lcsign) alpha += 90.0; } fixup(&alpha); *DEC = ASIN(SIN(lambda) * SIN(epsilon)); /* 10 */ fixup(DEC); fixup(&eastlongitude); HA = *L - alpha + 180 + 15 * UTHM + eastlongitude; /* 12 */ fixup(&HA); fixup(&latitude); #ifdef NOTDEF - printf("%02d/%02d %02d: l:%g d:%g h:%g\n", - inMM, inDD, inHOUR, latitude, *DEC, HA); + printf("%02d/%02d %02d:%02d:%02d l:%g d:%g h:%g\n", + inMM, inDD, inHOUR, inMIN, inSEC, latitude, *DEC, HA); #endif return; /* * The following calculations are not used, so to save time * they are not calculated. */ #ifdef NOTDEF *ALT = ASIN(SIN(latitude) * SIN(*DEC) + COS(latitude) * COS(*DEC) * COS(HA)); /* 13 */ fixup(ALT); *AZ = ATAN(SIN(HA) / (COS(HA) * SIN(latitude) - TAN(*DEC) * COS(latitude))); /* 14 */ if (*ALT > 180) *ALT -= 360; if (*ALT < -180) *ALT += 360; printf("a:%g a:%g\n", *ALT, *AZ); #endif #ifdef NOTDEF printf("Y:\t\t\t %d\t\t %d\t\t %d\n", Y, expY, Y - expY); comp("ZJ", ZJ, expZJ); comp("UTHM", UTHM, expUTHM); comp("D", D, expD); comp("T", T, expT); comp("L", L, fixup(&expL)); comp("M", M, fixup(&expM)); comp("epsilon", epsilon, fixup(&expepsilon)); comp("lambda", lambda, fixup(&explambda)); comp("alpha", alpha, fixup(&expalpha)); comp("DEC", DEC, fixup(&expDEC)); comp("eastlongitude", eastlongitude, fixup(&expeastlongitude)); comp("latitude", latitude, fixup(&explatitude)); comp("HA", HA, fixup(&expHA)); comp("ALT", ALT, fixup(&expALT)); comp("AZ", AZ, fixup(&expAZ)); #endif } #define SIGN(a) (((a) > 180) ? -1 : 1) #define ANGLE(a, b) (((a) < (b)) ? 1 : -1) #define SHOUR(s) ((s) / 3600) #define SMIN(s) (((s) % 3600) / 60) +#define SSEC(s) ((s) % 60) #define HOUR(h) ((h) / 4) #define MIN(h) (15 * ((h) % 4)) +#define SEC(h) 0 #define DEBUG1(y, m, d, hh, mm, pdec, dec) \ printf("%4d-%02d-%02d %02d:%02d:00 - %7.7g -> %7.7g\n", \ y, m, d, hh, mm, pdec, dec) #define DEBUG2(y, m, d, hh, mm, pdec, dec, pang, ang) \ printf("%4d-%02d-%02d %02d:%02d:00 - %7.7g -> %7.7g - %d -> %d\n", \ y, m, d, hh, mm, pdec, dec, pang, ang) void equinoxsolstice(int year, double UTCoffset, int *equinoxdays, int *solsticedays) { double fe[2], fs[2]; fequinoxsolstice(year, UTCoffset, fe, fs); equinoxdays[0] = round(fe[0]); equinoxdays[1] = round(fe[1]); solsticedays[0] = round(fs[0]); solsticedays[1] = round(fs[1]); } void fequinoxsolstice(int year, double UTCoffset, double *equinoxdays, double *solsticedays) { double dec, prevdec, L; int h, d, prevangle, angle; int found = 0; double decleft, decright, decmiddle; int dial, s; int *cumdays; cumdays = cumdaytab[isleap(year)]; /* * Find the first equinox, somewhere in March: * It happens when the returned value "dec" goes from * [350 ... 360> -> [0 ... 10] */ found = 0; prevdec = 350; for (d = 18; d < 31; d++) { // printf("Comparing day %d to %d.\n", d, d+1); - sunpos(year, 3, d, UTCoffset, 0, 0, 0.0, 0.0, &L, &decleft); - sunpos(year, 3, d + 1, UTCoffset, 0, 0, 0.0, 0.0, + sunpos(year, 3, d, UTCoffset, 0, 0, 0, 0.0, 0.0, &L, &decleft); + sunpos(year, 3, d + 1, UTCoffset, 0, 0, 0, 0.0, 0.0, &L, &decright); // printf("Found %g and %g.\n", decleft, decright); if (SIGN(decleft) == SIGN(decright)) continue; dial = SECSPERDAY; s = SECSPERDAY / 2; while (s > 0) { // printf("Obtaining %d (%02d:%02d)\n", // dial, SHOUR(dial), SMIN(dial)); - sunpos(year, 3, d, UTCoffset, SHOUR(dial), SMIN(dial), + sunpos(year, 3, d, UTCoffset, + SHOUR(dial), SMIN(dial), SSEC(dial), 0.0, 0.0, &L, &decmiddle); // printf("Found %g\n", decmiddle); if (SIGN(decleft) == SIGN(decmiddle)) { decleft = decmiddle; dial += s; } else { decright = decmiddle; dial -= s; } // printf("New boundaries: %g - %g\n", decleft, decright); s /= 2; } equinoxdays[0] = 1 + cumdays[3] + d + (dial / FSECSPERDAY); break; } /* Find the second equinox, somewhere in September: * It happens when the returned value "dec" goes from * [10 ... 0] -> <360 ... 350] */ found = 0; prevdec = 10; for (d = 18; d < 31; d++) { - printf("Comparing day %d to %d.\n", d, d+1); - sunpos(year, 9, d, UTCoffset, 0, 0, 0.0, 0.0, &L, &decleft); - sunpos(year, 9, d + 1, UTCoffset, 0, 0, 0.0, 0.0, +// printf("Comparing day %d to %d.\n", d, d+1); + sunpos(year, 9, d, UTCoffset, 0, 0, 0, 0.0, 0.0, &L, &decleft); + sunpos(year, 9, d + 1, UTCoffset, 0, 0, 0, 0.0, 0.0, &L, &decright); - printf("Found %g and %g.\n", decleft, decright); +// printf("Found %g and %g.\n", decleft, decright); if (SIGN(decleft) == SIGN(decright)) continue; dial = SECSPERDAY; s = SECSPERDAY / 2; while (s > 0) { // printf("Obtaining %d (%02d:%02d)\n", // dial, SHOUR(dial), SMIN(dial)); - sunpos(year, 9, d, UTCoffset, SHOUR(dial), SMIN(dial), + sunpos(year, 9, d, UTCoffset, + SHOUR(dial), SMIN(dial), SSEC(dial), 0.0, 0.0, &L, &decmiddle); // printf("Found %g\n", decmiddle); if (SIGN(decleft) == SIGN(decmiddle)) { decleft = decmiddle; dial += s; } else { decright = decmiddle; dial -= s; } // printf("New boundaries: %g - %g\n", decleft, decright); s /= 2; } equinoxdays[1] = 1 + cumdays[9] + d + (dial / FSECSPERDAY); break; } /* * Find the first solstice, somewhere in June: * It happens when the returned value "dec" peaks * [40 ... 45] -> [45 ... 40] */ found = 0; prevdec = 0; prevangle = 1; for (d = 18; d < 31; d++) { for (h = 0; h < 4 * HOURSPERDAY; h++) { - sunpos(year, 6, d, UTCoffset, HOUR(h), MIN(h), + sunpos(year, 6, d, UTCoffset, HOUR(h), MIN(h), SEC(h), 0.0, 0.0, &L, &dec); angle = ANGLE(prevdec, dec); if (prevangle != angle) { #ifdef NOTDEF DEBUG2(year, 6, d, HOUR(h), MIN(h), prevdec, dec, prevangle, angle); #endif solsticedays[0] = 1 + cumdays[6] + d + ((h / 4.0) / 24.0); found = 1; break; } prevdec = dec; prevangle = angle; } if (found) break; } /* * Find the second solstice, somewhere in December: * It happens when the returned value "dec" peaks * [315 ... 310] -> [310 ... 315] */ found = 0; prevdec = 360; prevangle = -1; for (d = 18; d < 31; d++) { for (h = 0; h < 4 * HOURSPERDAY; h++) { - sunpos(year, 12, d, UTCoffset, HOUR(h), MIN(h), + sunpos(year, 12, d, UTCoffset, HOUR(h), MIN(h), SEC(h), 0.0, 0.0, &L, &dec); angle = ANGLE(prevdec, dec); if (prevangle != angle) { #ifdef NOTDEF DEBUG2(year, 12, d, HOUR(h), MIN(h), prevdec, dec, prevangle, angle); #endif solsticedays[1] = 1 + cumdays[12] + d + ((h / 4.0) / 24.0); found = 1; break; } prevdec = dec; prevangle = angle; } if (found) break; } return; } int calculatesunlongitude30(int year, int degreeGMToffset, int *ichinesemonths) { int m, d, h; double dec; double curL, prevL; int *pichinesemonths, *monthdays, *cumdays, i; int firstmonth330; cumdays = cumdaytab[isleap(year)]; monthdays = mondaytab[isleap(year)]; pichinesemonths = ichinesemonths; sunpos(year - 1, 12, 31, -24 * (degreeGMToffset / 360.0), - HOUR(h), MIN(h), 0.0, 0.0, &prevL, &dec); + HOUR(h), MIN(h), SEC(h), 0.0, 0.0, &prevL, &dec); for (m = 1; m <= 12; m++) { for (d = 1; d <= monthdays[m]; d++) { for (h = 0; h < 4 * HOURSPERDAY; h++) { sunpos(year, m, d, -24 * (degreeGMToffset / 360.0), - HOUR(h), MIN(h), 0.0, 0.0, &curL, &dec); + HOUR(h), MIN(h), SEC(h), + 0.0, 0.0, &curL, &dec); if (curL < 180 && prevL > 180) { *pichinesemonths = cumdays[m] + d; #ifdef DEBUG printf("%04d-%02d-%02d %02d:%02d - %d %g\n", year, m, d, HOUR(h), MIN(h), *pichinesemonths, curL); #endif pichinesemonths++; } else { for (i = 0; i <= 360; i += 30) if (curL > i && prevL < i) { *pichinesemonths = cumdays[m] + d; #ifdef DEBUG printf("%04d-%02d-%02d %02d:%02d - %d %g\n", year, m, d, HOUR(h), MIN(h), *pichinesemonths, curL); #endif if (i == 330) firstmonth330 = *pichinesemonths; pichinesemonths++; } } prevL = curL; } } } *pichinesemonths = -1; return (firstmonth330); } #ifdef NOTDEF int main(int argc, char **argv) { /* year Mar June Sept Dec day time day time day time day time 2004 20 06:49 21 00:57 22 16:30 21 12:42 2005 20 12:33 21 06:46 22 22:23 21 18:35 2006 20 18:26 21 12:26 23 04:03 22 00:22 2007 21 00:07 21 18:06 23 09:51 22 06:08 2008 20 05:48 20 23:59 22 15:44 21 12:04 2009 20 11:44 21 05:45 22 21:18 21 17:47 2010 20 17:32 21 11:28 23 03:09 21 23:38 2011 20 23:21 21 17:16 23 09:04 22 05:30 2012 20 05:14 20 23:09 22 14:49 21 11:11 2013 20 11:02 21 05:04 22 20:44 21 17:11 2014 20 16:57 21 10:51 23 02:29 21 23:03 2015 20 22:45 21 16:38 23 08:20 22 04:48 2016 20 04:30 20 22:34 22 14:21 21 10:44 2017 20 10:28 21 04:24 22 20:02 21 16:28 */ int eq[2], sol[2]; equinoxsolstice(strtol(argv[1], NULL, 10), 0.0, eq, sol); printf("%d - %d - %d - %d\n", eq[0], sol[0], eq[1], sol[1]); return(0); } #endif Property changes on: user/edwin/calendar/sunpos.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property