Date: Fri, 25 Dec 2009 11:41:04 +0000 (UTC) From: Edwin Groothuis <edwin@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r200984 - user/edwin/calendar Message-ID: <200912251141.nBPBf4Tw060225@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: edwin Date: Fri Dec 25 11:41:04 2009 New Revision: 200984 URL: http://svn.freebsd.org/changeset/base/200984 Log: Intermittent commit: - Fix the handling of the years (leapyear / nonleapyear, span over multiple years) in Paskha and Easter handling. - Add code to properly handle absurd long intervals. Added: user/edwin/calendar/dates.c Modified: user/edwin/calendar/Makefile user/edwin/calendar/calendar.c user/edwin/calendar/calendar.h user/edwin/calendar/day.c user/edwin/calendar/events.c user/edwin/calendar/ostern.c user/edwin/calendar/paskha.c Modified: user/edwin/calendar/Makefile ============================================================================== --- user/edwin/calendar/Makefile Fri Dec 25 11:12:05 2009 (r200983) +++ user/edwin/calendar/Makefile Fri Dec 25 11:41:04 2009 (r200984) @@ -4,7 +4,8 @@ CFLAGS= -pipe -g -std=gnu99 -fstack-protector -Wall PROG= calendar -SRCS= calendar.c locale.c events.c parsedata.c io.c day.c ostern.c paskha.c +SRCS= calendar.c locale.c events.c dates.c parsedata.c io.c day.c \ + ostern.c paskha.c INTER= de_AT.ISO_8859-15 de_DE.ISO8859-1 fr_FR.ISO8859-1 \ hr_HR.ISO8859-2 hu_HU.ISO8859-2 ru_RU.KOI8-R uk_UA.KOI8-U DE_LINKS= de_DE.ISO8859-15 Modified: user/edwin/calendar/calendar.c ============================================================================== --- user/edwin/calendar/calendar.c Fri Dec 25 11:12:05 2009 (r200983) +++ user/edwin/calendar/calendar.c Fri Dec 25 11:41:04 2009 (r200984) @@ -129,7 +129,9 @@ main(int argc, char *argv[]) if (f_time <= 0) (void)time(&f_time); - settimes(f_time, f_dayBefore, f_dayAfter); + settimes(f_time, f_dayBefore, f_dayAfter, &tp1, &tp2); + generatedates(&tp1, &tp2); + dumpdates(); if (doall) while ((pw = getpwent()) != NULL) { Modified: user/edwin/calendar/calendar.h ============================================================================== --- user/edwin/calendar/calendar.h Fri Dec 25 11:12:05 2009 (r200983) +++ user/edwin/calendar/calendar.h Fri Dec 25 11:41:04 2009 (r200984) @@ -46,7 +46,6 @@ extern struct iovec header[]; extern struct tm tp1, tp2; extern time_t t1, t2; extern const char *calendarFile; -extern int *cumdays; extern int yrdays; extern struct fixs neaster, npaskha, ncny; @@ -114,7 +113,8 @@ extern const char *fdays[]; void setnnames(void); /* day.c */ -void settimes(time_t,int, int); +extern const struct tm tm0; +void settimes(time_t,int, int, struct tm *tp1, struct tm *tp2); time_t Mktime(char *); /* parsedata.c */ @@ -126,7 +126,10 @@ void closecal(FILE *); FILE *opencal(void); /* ostern.c / pashka.c */ -int geteaster(char *, int); -int getpaskha(char *, int); +int paskha(int); int easter(int); +/* dates.c */ +extern int cumdaytab[][14]; +void generatedates(struct tm *tp1, struct tm *tp2); +void dumpdates(void); Added: user/edwin/calendar/dates.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/edwin/calendar/dates.c Fri Dec 25 11:41:04 2009 (r200984) @@ -0,0 +1,226 @@ +#include <stdio.h> +#include <stdlib.h> +#include <err.h> +#include <time.h> + +#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; + struct cal_year *year; + struct event *events; +} cal_day; + +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 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 <m1 .. m2> + * - 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-<m1 .. 12] + * - Take all days from <y1 .. y2> + * - 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; + } +} Modified: user/edwin/calendar/day.c ============================================================================== --- user/edwin/calendar/day.c Fri Dec 25 11:12:05 2009 (r200983) +++ user/edwin/calendar/day.c Fri Dec 25 11:41:04 2009 (r200984) @@ -45,40 +45,26 @@ __FBSDID("$FreeBSD$"); struct tm tp1, tp2; time_t time1, time2; -static const struct tm tm0; -int *cumdays, yrdays; +const struct tm tm0; char dayname[10]; -/* 1-based month, 0-based days, cumulative */ -int daytab[][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}, -}; - - void -settimes(time_t now, int before, int after) +settimes(time_t now, int before, int after, struct tm *tp1, struct tm *tp2) { char *oldl, *lbufp; struct tm tp; localtime_r(&now, &tp); - if (isleap(tp.tm_year + 1900)) { - yrdays = 366; - cumdays = daytab[1]; - } else { - yrdays = 365; - cumdays = daytab[0]; - } + /* Friday displays Monday's events */ if (f_dayAfter == 0 && f_dayBefore == 0 && Friday != -1) f_dayAfter = tp.tm_wday == Friday ? 3 : 1; time1 = now - SECSPERDAY * f_dayBefore; - localtime_r(&time1, &tp1); + localtime_r(&time1, tp1); time2 = now + SECSPERDAY * f_dayAfter; - localtime_r(&time2, &tp2); + localtime_r(&time2, tp2); header[5].iov_base = dayname; Modified: user/edwin/calendar/events.c ============================================================================== --- user/edwin/calendar/events.c Fri Dec 25 11:12:05 2009 (r200983) +++ user/edwin/calendar/events.c Fri Dec 25 11:41:04 2009 (r200984) @@ -120,23 +120,23 @@ event_print_all(FILE *fp, struct event * for (daycounter = 0; daycounter <= f_dayAfter + f_dayBefore; daycounter++) { day = tp1.tm_yday - f_dayBefore + daycounter; - if (day < 0) - day += yrdays; - if (day >= yrdays) - day -= yrdays; +// if (day < 0) +// day += yrdays; +// if (day >= yrdays) +// day -= yrdays; /* * When we know the day of the year, we can determine the day * of the month and the month. */ - month = 1; - while (month <= 12) { - if (day <= cumdays[month]) - break; - month++; - } - month--; - day -= cumdays[month]; +// month = 1; +// while (month <= 12) { +// if (day <= cumdays[month]) +// break; +// month++; +// } +// month--; +// day -= cumdays[month]; #ifdef DEBUG fprintf(stderr, "event_print_allmonth: %d, day: %d\n", Modified: user/edwin/calendar/ostern.c ============================================================================== --- user/edwin/calendar/ostern.c Fri Dec 25 11:12:05 2009 (r200983) +++ user/edwin/calendar/ostern.c Fri Dec 25 11:41:04 2009 (r200984) @@ -60,7 +60,7 @@ easter(int year) /* 0 ... abcd, NOT sinc L = I - J; - if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) + if (isleap(year)) return 31 + 29 + 21 + L + 7; else return 31 + 28 + 21 + L + 7; Modified: user/edwin/calendar/paskha.c ============================================================================== --- user/edwin/calendar/paskha.c Fri Dec 25 11:12:05 2009 (r200983) +++ user/edwin/calendar/paskha.c Fri Dec 25 11:41:04 2009 (r200984) @@ -36,24 +36,24 @@ __FBSDID("$FreeBSD$"); #define PASKHA "paskha" #define PASKHALEN (sizeof(PASKHA) - 1) -static int paskha(int); - /* return year day for Orthodox Easter using Gauss formula */ /* (old style result) */ -static int +int paskha(int R) /*year*/ { int a, b, c, d, e; static int x = 15; static int y = 6; + int *cumday; a = R % 19; b = R % 4; c = R % 7; d = (19 * a + x) % 30; e = (2 * b + 4 * c + 6 * d + y) % 7; - return (((cumdays[3] + 1) + 22) + (d + e)); + cumday = cumdaytab[isleap(R)]; + return (((cumday[3] + 1) + 22) + (d + e)); } /* return year day for Orthodox Easter depending days */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200912251141.nBPBf4Tw060225>