wmbiff: fixed possible null-pointer dereference.
[dockapps.git] / wmcalendar / Src / calendarfunc.c
blob95fd73dadfbbc113c8aae3911a805f47627ac32a
1 /* persian calendar functions original code is by Kees Couprie
2 http://www.geocities.com/couprie/calmath/ */
4 /* islamic conversion and moonphase calculation is taken from
6 * hdate
8 * Copyright (c) 1992 by Waleed A. Muhanna
10 * Permission for nonprofit use and redistribution of this software and
11 * its documentation is hereby granted without fee, provided that the
12 * above copyright notice appear in all copies and that both that copyright
13 * notice and this permission notice appear in supporting documentation.
15 * No representation is made about the suitability of this software for any
16 * purpose. It is provided "as is" without express or implied warranty.
18 * Send any comments/suggestions/fixes/additions to:
19 * wmuhanna@magnus.acs.ohio-state.edu
23 #include "calendarfunc.h"
24 #include <stdio.h>
28 long persian_jdn(struct icaltimetype dt)
30 const long PERSIAN_EPOCH = 1948321; /* The JDN of 1 Farvardin 1*/
31 int epbase;
32 long epyear;
33 long mdays;
34 long jdn;
35 epbase = dt.year - 474;
36 epyear = 474 + (epbase % 2820);
37 if (dt.month <= 7)
38 mdays = (dt.month - 1) * 31;
39 else
40 mdays = (dt.month - 1) * 30 + 6;
41 jdn = dt.day + mdays ;
42 jdn += (((epyear * 682) - 110) / 2816) ;
43 jdn += (epyear - 1) * 365;
44 jdn += (epbase / 2820) * 1029983 ;
45 jdn += (PERSIAN_EPOCH - 1);
46 return jdn;
49 double tmoonphase( long n, int nph)
51 double jd, t, t2, t3, k, ma, sa, tf, xtra;
52 k = n + nph/4.0; t = k/1236.85; t2 = t*t; t3 = t2*t;
53 jd = 2415020.75933 + 29.53058868*k - 1.178e-4 * t2
54 - 1.55e-7 * t3
55 + 3.3e-4 * sin (RPD * (166.56 +132.87*t -0.009173*t2));
57 /* Sun's mean anomaly */
58 sa = RPD * (359.2242 + 29.10535608*k - 3.33e-5 * t2 - 3.47e-6 * t3);
60 /* Moon's mean anomaly */
61 ma = RPD * (306.0253 + 385.81691806*k + 0.0107306*t2 +1.236e-5 *t3);
63 /* Moon's argument of latitude */
64 tf = RPD * 2.0 * (21.2964 + 390.67050646*k -0.0016528*t2
65 -2.39e-6 * t3);
67 /* should reduce to interval 0-1.0 before calculating further */
68 if (nph==0 || nph==2)
69 /* Corrections for New and Full Moon */
70 xtra = (0.1734 - 0.000393*t) * sin(sa)
71 +0.0021*sin(sa*2)
72 -0.4068*sin(ma) +0.0161*sin(2*ma) -0.0004*sin(3*ma)
73 +0.0104*sin(tf)
74 -0.0051*sin(sa+ma) -0.0074*sin(sa-ma)
75 +0.0004*sin(tf+sa) -0.0004*sin(tf-sa)
76 -0.0006*sin(tf+ma) +0.0010*sin(tf-ma)
77 +0.0005*sin(sa+ 2*ma);
78 else if (nph==1 || nph==3) {
79 xtra = (0.1721 - 0.0004*t) * sin(sa)
80 +0.0021*sin(sa*2)
81 -0.6280*sin(ma) +0.0089*sin(2*ma) -0.0004*sin(3*ma)
82 +0.0079*sin(tf)
83 -0.0119*sin(sa+ma) -0.0047*sin(sa-ma)
84 +0.0003*sin(tf+sa) -0.0004*sin(tf-sa)
85 -0.0006*sin(tf+ma) +0.0021*sin(tf-ma)
86 +0.0003*sin(sa+ 2*ma) +0.0004*sin(sa-2*ma)
87 -0.0003*sin(2*sa+ma);
88 if (nph==1)
89 xtra = xtra +0.0028 -0.0004*cos(sa) +0.0003*cos(ma);
90 else
91 xtra = xtra -0.0028 +0.0004*cos(sa) -0.0003*cos(ma);
92 } else {
93 printf("tmoonphase: illegal phase number\n");
94 exit(1);
96 /* convert from Ephemeris Time (ET) to (approximate)
97 Universal Time (UT) */
98 jd += xtra - (0.41 +1.2053*t +0.4992*t2)/1440;
99 return (jd);
103 double visible(long n,double * rjd)
105 double jd;
106 float tf;
107 long d;
109 jd = tmoonphase(n,0);
110 *rjd = jd;
111 d = jd;
112 tf = (jd - d);
113 if (tf<=0.5) /*new moon starts in the afternoon */
114 return(jd+1.0);
115 /* new moon starts before noon */
116 tf = (tf-0.5)*24 +TIMZ; /* local time */
117 if (tf>TIMDIF) return(jd+1.0); /*age at sunset < min for visiblity*/
118 return(jd);
122 struct icaltimetype jdn_islamic(long jdn)
124 struct icaltimetype h;
125 double mjd, rjd;
126 long k, hm;
128 /* obtain first approx. of how many new moons since the beginning
129 of the year 1900 */
130 h = jdn_civil(jdn);
131 k = 0.6 + (h.year + ((int) (h.month - 0.5)) / 12.0 + h.day
132 / 365.0 - 1900) * 12.3685;
134 mjd = visible(k--, &rjd);
135 } while (mjd > jdn);
136 k++;
137 /*first of the month is the following day*/
138 hm = k - 1048;
139 h.year = 1405 + (hm / 12);
141 h.month = (hm % 12) +1;
142 if (hm != 0 && h.month <= 0) {
143 h.month += 12;
144 h.year--;
146 if (h.year<=0)
147 h.year--;
148 h.day = jdn - mjd + 1;
150 return h;
154 long islamic_jdn(struct icaltimetype dt)
156 double jd, rjd;
157 long k;
159 k = dt.month + dt.year * 12 - NMONTHS; /* # of m since 1/1/1405 */
160 jd = visible(k + 1048L, &rjd) + dt.day;
161 return jd;
167 struct icaltimetype jdn_persian(long jdn)
169 struct icaltimetype ret, h;
170 int iYear, iMonth, iDay;
171 int depoch;
172 int cycle;
173 int cyear;
174 int ycycle;
175 int aux1, aux2;
176 int yday;
177 h.day = 1;
178 h.month = 1;
179 h.year = 475;
180 depoch = jdn - persian_jdn(h);
181 cycle = depoch / 1029983;
182 cyear = depoch % 1029983;
183 if( cyear == 1029982)
184 ycycle = 2820;
185 else{
186 aux1 = cyear / 366;
187 aux2 = cyear % 366;
188 ycycle = (((2134 * aux1) + (2816 * aux2) + 2815) / 1028522) + aux1 + 1;
190 iYear = ycycle + (2820 * cycle) + 474;
191 if (iYear <= 0)
192 iYear = iYear - 1;
193 h.year = iYear;
194 yday = (jdn - persian_jdn(h)) + 1;
195 if(yday <= 186 )
196 iMonth = Ceil((yday-1) / 31);
197 else
198 iMonth = Ceil((yday - 7) / 30);
199 iMonth++;
200 h.month = iMonth;
201 iDay = (jdn - persian_jdn(h)) + 1;
202 ret.day = iDay;
203 ret.month = iMonth;
204 ret.year = iYear;
205 ret.is_date = 1;
206 return ret;
211 int Ceil(float number)
213 int ret;
214 if(number>0)
215 number += 0.5;
216 ret = number;
217 return ret;
222 long civil_jdn(struct icaltimetype dt)
224 long jdn = ((1461 * (dt.year + 4800 + ((dt.month - 14) / 12))) / 4)
225 + ((367 * (dt.month - 2 - 12 * (((dt.month - 14) / 12)))) / 12)
226 - ((3 * (((dt.year + 4900 + ((dt.month - 14) / 12)) / 100))) / 4)
227 + dt.day - 32075;
228 return jdn;
233 struct icaltimetype jdn_civil(long jdn)
235 long l, n, i, j;
236 struct icaltimetype ret;
237 int iday, imonth, iyear;
238 l = jdn + 68569;
239 n = ((4 * l) / 146097);
240 l = l - ((146097 * n + 3) / 4);
241 i = ((4000 * (l + 1)) / 1461001);
242 l = l - ((1461 * i) / 4) + 31;
243 j = ((80 * l) / 2447);
244 iday = l - ((2447 * j) / 80);
245 l = (j / 11);
246 imonth = j + 2 - 12 * l;
247 iyear = 100 * (n - 49) + i + l;
248 ret.day = iday;
249 ret.month = imonth;
250 ret.year = iyear;
251 ret.hour = 0;
252 ret.minute = 0;
253 ret.second = 0;
254 return ret;
259 struct icaltimetype civil_persian(struct icaltimetype dt)
261 return(jdn_persian(civil_jdn(dt)));
265 struct icaltimetype civil_islamic(struct icaltimetype dt)
267 return(jdn_islamic(civil_jdn(dt)));
272 struct icaltimetype persian_civil(struct icaltimetype dt)
274 return(jdn_civil(persian_jdn(dt)));
278 struct icaltimetype islamic_civil(struct icaltimetype dt)
280 return(jdn_civil(islamic_jdn(dt)));
283 struct icaltimetype get_civil(struct icaltimetype dt, int calendar){
284 if(calendar == 0)
285 return dt;
286 else if(calendar == 1)
287 return persian_civil(dt);
288 else if(calendar == 2)
289 return islamic_civil(dt);
294 int isPersianLeap(int year)
296 struct icaltimetype dt, dold;
298 dt.year = year;
299 dt.month = 12;
300 dt.day = 30;
301 dold = jdn_civil(2453108);
302 dt = civil_persian(persian_civil(dt));
303 if(dt.day == 1)
304 return 0;
305 return 1 ;
308 int isGregorianLeap(int year)
310 if(year % 4 !=0)
311 return 0;
312 if(year % 100 == 0 && year % 400 != 0)
313 return 0;
314 return 1;
317 int days_in_month(int month, int year, int calendar)
319 if(calendar == 0)
320 return days_in_gregorian_month(month, year);
321 else if(calendar == 1)
322 return days_in_persian_month(month, year);
323 else if(calendar == 2)
324 return days_in_islamic_month(month, year);
329 int days_in_persian_month(int month, int year)
331 if(month < 7)
332 return 31;
333 if(month < 12)
334 return 30;
335 if(isPersianLeap(year))
336 return 30;
337 return 29;
341 int days_in_islamic_month(int month, int year)
343 struct icaltimetype dt, dold;
344 month++;
345 if(month == 13){
346 month = 1;
347 year++;
349 dt.year = year;
350 dt.month = month;
351 dt.day = 1;
352 dt = jdn_islamic(islamic_jdn(dt) - 1);
353 return dt.day;
357 int days_in_gregorian_month(int month, int year)
359 switch(month){
360 case 4:
361 case 6:
362 case 9:
363 case 11:
364 return 30;
365 case 2:
366 return 28 + isGregorianLeap(year);
367 default:
368 return 31;
372 int day_of_week(struct icaltimetype dt)
374 int jd;
375 jd = civil_jdn(dt);
376 jd --;
377 return jd % 7;
380 int moon(struct icaltimetype h)
382 int k, jd, i ,j, jdn;
383 long mjd = 0;
384 jd = civil_jdn(h);
385 if(datemoon[jd%200][1] == jd)
386 return datemoon[jd%200][0];
388 k = 1 + (h.year + ((int) (h.month - 0.5)) / 12.0 + h.day / 365.0 - 1900) * 12.3685;
389 do {
390 mjd = tmoonphase(k--, 0);
391 } while (mjd > jd);
393 k--;
395 for(i = tmoonphase(k,0); i < tmoonphase(k+5,0 ); i++){
396 datemoon[i%200][0] = 0;
397 datemoon[i%200][1] = i;
400 for(j = 0; j < 6; j++){
401 for(i = 0; i < 4; i++){
402 mjd = tmoonphase(k, i);
403 datemoon[mjd%200][0] = i+1;
404 datemoon[mjd%200][1] = mjd;
406 k++;
409 if(datemoon[jd%200][1] == jd)
410 return datemoon[jd%200][0];
411 return 0;
415 int daysComp(struct icaltimetype d1, struct icaltimetype d2){
416 if(d1.year < d2.year)
417 return 1; /* d1 < d2 */
418 if(d1.year > d2.year)
419 return 2; /* d1 > d2 */
421 /* years are equal */
422 if(d1.month < d2.month)
423 return 1; /* d1 < d2 */
424 if(d1.month > d2.month)
425 return 2; /* d1 > d2 */
427 /* months are equal */
428 if(d1.day < d2.day)
429 return 1; /* d1 < d2 */
430 if(d1.day > d2.day)
431 return 2; /* d1 > d2 */
433 return 0; /* days are equal */
437 int daysEqual(struct icaltimetype d1, struct icaltimetype d2){
438 if(daysComp(d1, d2) == 0)
439 return 1;
440 return 0;
444 int daysLater(struct icaltimetype d1, struct icaltimetype d2){
445 if(daysComp(d1, d2) == 1)
446 return 1;
447 return 0;
451 int daysEarlier(struct icaltimetype d1, struct icaltimetype d2){
452 if(daysComp(d1, d2) == 2)
453 return 1;
454 return 0;
458 int daysLaterEqual(struct icaltimetype d1, struct icaltimetype d2){
459 if(daysComp(d1, d2) != 2)
460 return 1;
461 return 0;
465 int daysEarlierEqual(struct icaltimetype d1, struct icaltimetype d2){
466 if(daysComp(d1, d2) != 1)
467 return 1;
468 return 0;