2 * Copyright (c) 1992-2009 Edwin Groothuis <edwin@FreeBSD.org>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
39 int year; /* 19xx, 20xx, 21xx */
40 int easter; /* Julian day */
41 int paskha; /* Julian day */
42 int cny; /* Julian day */
43 int firstdayofweek; /* 0 .. 6 */
44 struct cal_month *months;
45 struct cal_year *nextyear;
49 int month; /* 01 .. 12 */
50 int firstdayjulian; /* 000 .. 366 */
51 int firstdayofweek; /* 0 .. 6 */
52 struct cal_year *year; /* points back */
54 struct cal_month *nextmonth;
58 int dayofmonth; /* 01 .. 31 */
59 int julianday; /* 000 .. 366 */
60 int dayofweek; /* 0 .. 6 */
61 struct cal_day *nextday;
62 struct cal_month *month; /* points back */
63 struct cal_year *year; /* points back */
67 int debug_remember = 0;
68 struct cal_year *hyear = NULL;
70 /* 1-based month, 0-based days, cumulative */
72 int cumdaytab[][14] = {
73 {0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364},
74 {0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
76 /* 1-based month, individual */
78 int mondaytab[][14] = {
79 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30},
80 {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30},
83 static struct cal_day * find_day(int yy, int mm, int dd);
86 createdate(int y, int m, int d)
88 struct cal_year *py, *pyp;
89 struct cal_month *pm, *pmp;
90 struct cal_day *pd, *pdp;
96 if (py->year == y + 1900)
105 py = (struct cal_year *)calloc(1, sizeof(struct cal_year));
107 py->easter = easter(y);
108 py->paskha = paskha(y);
114 localtime_r(&t, &td);
115 py->firstdayofweek = td.tm_wday;
121 /* The very very very first one */
135 pm = (struct cal_month *)calloc(1, sizeof(struct cal_month));
138 cumday = cumdaytab[isleap(y)];
139 pm->firstdayjulian = cumday[m] + 2;
141 (py->firstdayofweek + pm->firstdayjulian -1) % 7;
155 if (pd == NULL) { /* Always true */
156 pd = (struct cal_day *)calloc(1, sizeof(struct cal_day));
160 pd->julianday = pm->firstdayjulian + d - 1;
161 pd->dayofweek = (pm->firstdayofweek + d - 1) % 7;
170 generatedates(struct tm *tp1, struct tm *tp2)
177 m1 = tp1->tm_mon + 1;
180 m2 = tp2->tm_mon + 1;
185 /* Same year, same month. Easy! */
186 for (d = d1; d <= d2; d++)
187 createdate(y1, m1, d);
191 * Same year, different month.
192 * - Take the leftover days from m1
193 * - Take all days from <m1 .. m2>
194 * - Take the first days from m2
196 mondays = mondaytab[isleap(y1)];
197 for (d = d1; d <= mondays[m1]; d++)
198 createdate(y1, m1, d);
199 for (m = m1 + 1; m < m2; m++)
200 for (d = 1; d <= mondays[m]; d++)
201 createdate(y1, m, d);
202 for (d = 1; d <= d2; d++)
203 createdate(y1, m2, d);
207 * Different year, different month.
208 * - Take the leftover days from y1-m1
209 * - Take all days from y1-<m1 .. 12]
210 * - Take all days from <y1 .. y2>
211 * - Take all days from y2-[1 .. m2>
212 * - Take the first days of y2-m2
214 mondays = mondaytab[isleap(y1)];
215 for (d = d1; d <= mondays[m1]; d++)
216 createdate(y1, m1, d);
217 for (m = m1 + 1; m <= 12; m++)
218 for (d = 1; d <= mondays[m]; d++)
219 createdate(y1, m, d);
220 for (y = y1 + 1; y < y2; y++) {
221 mondays = mondaytab[isleap(y)];
222 for (m = 1; m <= 12; m++)
223 for (d = 1; d <= mondays[m]; d++)
226 mondays = mondaytab[isleap(y2)];
227 for (m = 1; m < m2; m++)
228 for (d = 1; d <= mondays[m]; d++)
229 createdate(y2, m, d);
230 for (d = 1; d <= d2; d++)
231 createdate(y2, m2, d);
243 printf("%-5d (wday:%d)\n", y->year, y->firstdayofweek);
246 printf("-- %-5d (julian:%d, dow:%d)\n", m->month,
247 m->firstdayjulian, m->firstdayofweek);
250 printf(" -- %-5d (julian:%d, dow:%d)\n",
251 d->dayofmonth, d->julianday, d->dayofweek);
261 remember_ymd(int yy, int mm, int dd)
268 printf("remember_ymd: %d - %d - %d\n", yy, mm, dd);
278 if (m->month != mm) {
284 if (d->dayofmonth == dd)
297 remember_yd(int yy, int dd, int *rm, int *rd)
304 printf("remember_yd: %d - %d\n", yy, dd);
316 if (d->julianday == dd) {
331 first_dayofweek_of_year(int yy)
338 return (y->firstdayofweek);
342 /* Should not happen */
347 first_dayofweek_of_month(int yy, int mm)
361 return (m->firstdayofweek);
364 /* Should not happen */
368 /* Should not happen */
373 walkthrough_dates(struct event **e)
375 static struct cal_year *y = NULL;
376 static struct cal_month *m = NULL;
377 static struct cal_day *d = NULL;
386 if (d->nextday != NULL) {
391 if (m->nextmonth != NULL) {
397 if (y->nextyear != NULL) {
408 static struct cal_day *
409 find_day(int yy, int mm, int dd)
416 printf("remember_ymd: %d - %d - %d\n", yy, mm, dd);
426 if (m->month != mm) {
432 if (d->dayofmonth == dd)
445 addtodate(struct event *e, int year, int month, int day)
449 d = find_day(year, month, day);