1 /*
2 Hebcal - A Jewish Calendar Generator
3 Copyright (C) 1994-2004 Danny Sadinoff
4 Portions Copyright (c) 2002 Michael J. Radwin. All Rights Reserved.
5
6 https://github.com/hebcal/hebcal
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 Danny Sadinoff can be reached at
23 danny@sadinoff.com
24 */
25
26
27 #include <stdio.h>
28 #include "danlib.h"
29 #include <time.h>
30 #include <string.h>
31 #include "myerror.h"
32 #include "greg.h"
33
34 /* greg.c gregorian calendar module for hebrew calendar program
35 By Danny Sadinoff
36 (C) 1992
37
38 */
39
40 const char *eMonths[] =
41 {
42 "UNUSED",
43 "January", "February", "March", "April", "May", "June", "July",
44 "August", "September", "October", "November", "December"
45 };
46
47 int MonthLengths[][13] =
48 {
49 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
50 {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
51 };
52
53 const char *ShortDayNames[] =
54 {
55 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
56 };
57
58
59 /*
60 *Return the day number within the year of the date DATE.
61 *For example, dayOfYear({1,1,1987}) returns the value 1
62 *while dayOfYear({12,31,1980}) returns 366.
63 */
64
65
dayOfYear(date_t d)66 int dayOfYear( date_t d )
67 {
68 int dOY = d.dd + 31 * (d.mm - 1);
69 if (d.mm > FEB)
70 {
71 dOY -= (4 * d.mm + 23) / 10;
72 if (LEAP (d.yy))
73 dOY++;
74 }
75 return dOY;
76 }
77
78
79 /*
80 * The number of days elapsed between the Gregorian date 12/31/1 BC and DATE.
81 * The Gregorian date Sunday, December 31, 1 BC is imaginary.
82 */
greg2abs(date_t d)83 long int greg2abs( date_t d ) /* "absolute date" */
84 {
85 return ((long) dayOfYear (d) /* days this year */
86 + 365L * (long) (d.yy - 1) /* + days in prior years */
87 + (long) ((d.yy - 1) / 4 /* + Julian Leap years */
88 - (d.yy - 1) / 100 /* - century years */
89 + (d.yy - 1) / 400)); /* + Gregorian leap years */
90 }
91
92 /*
93 * See the footnote on page 384 of ``Calendrical Calculations, Part II:
94 * Three Historical Calendars'' by E. M. Reingold, N. Dershowitz, and S. M.
95 * Clamen, Software--Practice and Experience, Volume 23, Number 4
96 * (April, 1993), pages 383-404 for an explanation.
97 */
abs2greg(long theDate)98 date_t abs2greg( long theDate )
99 {
100 int day, year, month, mlen;
101 date_t d;
102 long int d0, n400, d1, n100, d2, n4, d3, n1;
103
104 d0 = theDate - 1L;
105 n400 = d0 / 146097L;
106 d1 = d0 % 146097L;
107 n100 = d1 / 36524L;
108 d2 = d1 % 36524L;
109 n4 = d2 / 1461L;
110 d3 = d2 % 1461L;
111 n1 = d3 / 365L;
112
113 day = (int) ((d3 % 365L) + 1L);
114 year = (int) (400L * n400 + 100L * n100 + 4L * n4 + n1);
115
116 if (4L == n100 || 4L == n1)
117 {
118 d.mm = 12;
119 d.dd = 31;
120 d.yy = year;
121 return d;
122 }
123 else
124 {
125 year++;
126 month = 1;
127 while ((mlen = MonthLengths[LEAP (year)][month]) < day)
128 {
129 day -= mlen;
130 month++;
131 }
132 d.yy = year;
133 d.mm = month;
134 d.dd = day;
135 return d;
136 }
137 }
138
incDate(date_t * dt,long n)139 void incDate (date_t *dt, long n) /* increments dt by n days */
140 {
141 *dt = abs2greg (greg2abs (*dt) + n);
142 }
143
144
dayOfWeek(date_t d1)145 int dayOfWeek(date_t d1) /* sunday = 0 */
146 {
147 return (int) (greg2abs (d1) % 7L);
148 }
149
setDate(date_t * d)150 void setDate ( date_t *d )
151 {
152 /*
153 asctime() converts a time value contained in a tm structure
154 to a 26-character string of the form:
155 Sun Sep 16 01:03:52 1973\n\0
156 Each field has a constant width. asctime() returns a
157 pointer to the string.
158 */
159
160 /*
161 FIX: removing these decls, but need to start doing compilation platofrm checks to ensure that these aren't necessary.
162 time_t time ();
163 char *ctime( const time_t * );
164 */
165 time_t secs = time (NULL);
166 char *timestr = ctime (&secs);
167
168 /* portability has driven me to truly shameful code.
169 please forgive this.
170 */
171 sscanf (timestr + 20, "%d", &d->yy);
172 d->mm = lookup_string( timestr + 4, eMonths, 13, 3 );
173 sscanf (timestr + 8, "%d", &d->dd);
174 }
175
176
177 /** Returns the absolute date of the DAYNAME on or before absolute DATE.
178 * DAYNAME=0 means Sunday, DAYNAME=1 means Monday, and so on.
179
180
181 * Note: Applying this function to d+6 gives us the DAYNAME on or after an
182 * absolute day d. Similarly, applying it to d+3 gives the DAYNAME nearest to
183 * absolute date d, applying it to d-1 gives the DAYNAME previous to absolute
184 * date d, and applying it to d+7 gives the DAYNAME following absolute date d.
185
186 **/
day_on_or_before(int day_of_week,long date)187 long day_on_or_before( int day_of_week, long date)
188 {
189 return date - ((date - (long) day_of_week) % 7L);
190 }
191
192
193
194 /** (defun calendar-nth-named-day (n dayname month year &optional day)
195 "The date of Nth DAYNAME in MONTH, YEAR before/after optional DAY.
196 A DAYNAME of 0 means Sunday, 1 means Monday, and so on. If N<0,
197 return the Nth DAYNAME before MONTH DAY, YEAR (inclusive).
198 If N>0, return the Nth DAYNAME after MONTH DAY, YEAR (inclusive).
199
200 If DAY is omitted, it defaults to 1 if N>0, and MONTH's last day otherwise.
201 (calendar-gregorian-from-absolute
202 (if (> n 0)
203 (+ (* 7 (1- n))
204 (calendar-dayname-on-or-before
205 dayname
206 (+ 6 (calendar-absolute-from-gregorian
207 (list month (or day 1) year)))))
208 (+ (* 7 (1+ n))
209 (calendar-dayname-on-or-before
210 dayname
211 (calendar-absolute-from-gregorian
212 (list month
213 (or day (calendar-last-day-of-month month year))
214 year)))))))
215 */
216