svn commit: r200984 - user/edwin/calendar
Edwin Groothuis
edwin at FreeBSD.org
Fri Dec 25 11:41:05 UTC 2009
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 */
More information about the svn-src-user
mailing list