dockapps/wmcalendar/Src/calendarfunc.c
2014-10-05 19:18:49 +01:00

470 lines
10 KiB
C

/* persian calendar functions original code is by Kees Couprie
http://www.geocities.com/couprie/calmath/ */
/* islamic conversion and moonphase calculation is taken from
*
* hdate
*
* Copyright (c) 1992 by Waleed A. Muhanna
*
* Permission for nonprofit use and redistribution of this software and
* its documentation is hereby granted without fee, provided that the
* above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation.
*
* No representation is made about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
* Send any comments/suggestions/fixes/additions to:
* wmuhanna@magnus.acs.ohio-state.edu
*
*/
#include "calendarfunc.h"
#include <stdio.h>
long persian_jdn(struct icaltimetype dt)
{
const long PERSIAN_EPOCH = 1948321; /* The JDN of 1 Farvardin 1*/
int epbase;
long epyear;
long mdays;
long jdn;
epbase = dt.year - 474;
epyear = 474 + (epbase % 2820);
if (dt.month <= 7)
mdays = (dt.month - 1) * 31;
else
mdays = (dt.month - 1) * 30 + 6;
jdn = dt.day + mdays ;
jdn += (((epyear * 682) - 110) / 2816) ;
jdn += (epyear - 1) * 365;
jdn += (epbase / 2820) * 1029983 ;
jdn += (PERSIAN_EPOCH - 1);
return jdn;
}
double tmoonphase( long n, int nph)
{
double jd, t, t2, t3, k, ma, sa, tf, xtra;
k = n + nph/4.0; t = k/1236.85; t2 = t*t; t3 = t2*t;
jd = 2415020.75933 + 29.53058868*k - 1.178e-4 * t2
- 1.55e-7 * t3
+ 3.3e-4 * sin (RPD * (166.56 +132.87*t -0.009173*t2));
/* Sun's mean anomaly */
sa = RPD * (359.2242 + 29.10535608*k - 3.33e-5 * t2 - 3.47e-6 * t3);
/* Moon's mean anomaly */
ma = RPD * (306.0253 + 385.81691806*k + 0.0107306*t2 +1.236e-5 *t3);
/* Moon's argument of latitude */
tf = RPD * 2.0 * (21.2964 + 390.67050646*k -0.0016528*t2
-2.39e-6 * t3);
/* should reduce to interval 0-1.0 before calculating further */
if (nph==0 || nph==2)
/* Corrections for New and Full Moon */
xtra = (0.1734 - 0.000393*t) * sin(sa)
+0.0021*sin(sa*2)
-0.4068*sin(ma) +0.0161*sin(2*ma) -0.0004*sin(3*ma)
+0.0104*sin(tf)
-0.0051*sin(sa+ma) -0.0074*sin(sa-ma)
+0.0004*sin(tf+sa) -0.0004*sin(tf-sa)
-0.0006*sin(tf+ma) +0.0010*sin(tf-ma)
+0.0005*sin(sa+ 2*ma);
else if (nph==1 || nph==3) {
xtra = (0.1721 - 0.0004*t) * sin(sa)
+0.0021*sin(sa*2)
-0.6280*sin(ma) +0.0089*sin(2*ma) -0.0004*sin(3*ma)
+0.0079*sin(tf)
-0.0119*sin(sa+ma) -0.0047*sin(sa-ma)
+0.0003*sin(tf+sa) -0.0004*sin(tf-sa)
-0.0006*sin(tf+ma) +0.0021*sin(tf-ma)
+0.0003*sin(sa+ 2*ma) +0.0004*sin(sa-2*ma)
-0.0003*sin(2*sa+ma);
if (nph==1)
xtra = xtra +0.0028 -0.0004*cos(sa) +0.0003*cos(ma);
else
xtra = xtra -0.0028 +0.0004*cos(sa) -0.0003*cos(ma);
} else {
printf("tmoonphase: illegal phase number\n");
exit(1);
}
/* convert from Ephemeris Time (ET) to (approximate)
Universal Time (UT) */
jd += xtra - (0.41 +1.2053*t +0.4992*t2)/1440;
return (jd);
}
double visible(long n,double * rjd)
{
double jd;
float tf;
long d;
jd = tmoonphase(n,0);
*rjd = jd;
d = jd;
tf = (jd - d);
if (tf<=0.5) /*new moon starts in the afternoon */
return(jd+1.0);
/* new moon starts before noon */
tf = (tf-0.5)*24 +TIMZ; /* local time */
if (tf>TIMDIF) return(jd+1.0); /*age at sunset < min for visiblity*/
return(jd);
}
struct icaltimetype jdn_islamic(long jdn)
{
struct icaltimetype h;
double mjd, rjd;
long k, hm;
/* obtain first approx. of how many new moons since the beginning
of the year 1900 */
h = jdn_civil(jdn);
k = 0.6 + (h.year + ((int) (h.month - 0.5)) / 12.0 + h.day
/ 365.0 - 1900) * 12.3685;
do{
mjd = visible(k--, &rjd);
} while (mjd > jdn);
k++;
/*first of the month is the following day*/
hm = k - 1048;
h.year = 1405 + (hm / 12);
h.month = (hm % 12) +1;
if (hm != 0 && h.month <= 0) {
h.month += 12;
h.year--;
}
if (h.year<=0)
h.year--;
h.day = jdn - mjd + 1;
return h;
}
long islamic_jdn(struct icaltimetype dt)
{
double jd, rjd;
long k;
k = dt.month + dt.year * 12 - NMONTHS; /* # of m since 1/1/1405 */
jd = visible(k + 1048L, &rjd) + dt.day;
return jd;
}
struct icaltimetype jdn_persian(long jdn)
{
struct icaltimetype ret, h;
int iYear, iMonth, iDay;
int depoch;
int cycle;
int cyear;
int ycycle;
int aux1, aux2;
int yday;
h.day = 1;
h.month = 1;
h.year = 475;
depoch = jdn - persian_jdn(h);
cycle = depoch / 1029983;
cyear = depoch % 1029983;
if( cyear == 1029982)
ycycle = 2820;
else{
aux1 = cyear / 366;
aux2 = cyear % 366;
ycycle = (((2134 * aux1) + (2816 * aux2) + 2815) / 1028522) + aux1 + 1;
}
iYear = ycycle + (2820 * cycle) + 474;
if (iYear <= 0)
iYear = iYear - 1;
h.year = iYear;
yday = (jdn - persian_jdn(h)) + 1;
if(yday <= 186 )
iMonth = Ceil((yday-1) / 31);
else
iMonth = Ceil((yday - 7) / 30);
iMonth++;
h.month = iMonth;
iDay = (jdn - persian_jdn(h)) + 1;
ret.day = iDay;
ret.month = iMonth;
ret.year = iYear;
ret.is_date = 1;
return ret;
}
int Ceil(float number)
{
int ret;
if(number>0)
number += 0.5;
ret = number;
return ret;
}
long civil_jdn(struct icaltimetype dt)
{
long jdn = ((1461 * (dt.year + 4800 + ((dt.month - 14) / 12))) / 4)
+ ((367 * (dt.month - 2 - 12 * (((dt.month - 14) / 12)))) / 12)
- ((3 * (((dt.year + 4900 + ((dt.month - 14) / 12)) / 100))) / 4)
+ dt.day - 32075;
return jdn;
}
struct icaltimetype jdn_civil(long jdn)
{
long l, n, i, j;
struct icaltimetype ret;
int iday, imonth, iyear;
l = jdn + 68569;
n = ((4 * l) / 146097);
l = l - ((146097 * n + 3) / 4);
i = ((4000 * (l + 1)) / 1461001);
l = l - ((1461 * i) / 4) + 31;
j = ((80 * l) / 2447);
iday = l - ((2447 * j) / 80);
l = (j / 11);
imonth = j + 2 - 12 * l;
iyear = 100 * (n - 49) + i + l;
ret.day = iday;
ret.month = imonth;
ret.year = iyear;
ret.hour = 0;
ret.minute = 0;
ret.second = 0;
return ret;
}
struct icaltimetype civil_persian(struct icaltimetype dt)
{
return(jdn_persian(civil_jdn(dt)));
}
struct icaltimetype civil_islamic(struct icaltimetype dt)
{
return(jdn_islamic(civil_jdn(dt)));
}
struct icaltimetype persian_civil(struct icaltimetype dt)
{
return(jdn_civil(persian_jdn(dt)));
}
struct icaltimetype islamic_civil(struct icaltimetype dt)
{
return(jdn_civil(islamic_jdn(dt)));
}
struct icaltimetype get_civil(struct icaltimetype dt, int calendar){
if(calendar == 0)
return dt;
else if(calendar == 1)
return persian_civil(dt);
else if(calendar == 2)
return islamic_civil(dt);
}
int isPersianLeap(int year)
{
struct icaltimetype dt, dold;
dt.year = year;
dt.month = 12;
dt.day = 30;
dold = jdn_civil(2453108);
dt = civil_persian(persian_civil(dt));
if(dt.day == 1)
return 0;
return 1 ;
}
int isGregorianLeap(int year)
{
if(year % 4 !=0)
return 0;
if(year % 100 == 0 && year % 400 != 0)
return 0;
return 1;
}
int days_in_month(int month, int year, int calendar)
{
if(calendar == 0)
return days_in_gregorian_month(month, year);
else if(calendar == 1)
return days_in_persian_month(month, year);
else if(calendar == 2)
return days_in_islamic_month(month, year);
}
int days_in_persian_month(int month, int year)
{
if(month < 7)
return 31;
if(month < 12)
return 30;
if(isPersianLeap(year))
return 30;
return 29;
}
int days_in_islamic_month(int month, int year)
{
struct icaltimetype dt, dold;
month++;
if(month == 13){
month = 1;
year++;
}
dt.year = year;
dt.month = month;
dt.day = 1;
dt = jdn_islamic(islamic_jdn(dt) - 1);
return dt.day;
}
int days_in_gregorian_month(int month, int year)
{
switch(month){
case 4:
case 6:
case 9:
case 11:
return 30;
case 2:
return 28 + isGregorianLeap(year);
default:
return 31;
}
}
int day_of_week(struct icaltimetype dt)
{
int jd;
jd = civil_jdn(dt);
jd --;
return jd % 7;
}
int moon(struct icaltimetype h)
{
int k, jd, i ,j, jdn;
long mjd = 0;
jd = civil_jdn(h);
if(datemoon[jd%200][1] == jd)
return datemoon[jd%200][0];
k = 1 + (h.year + ((int) (h.month - 0.5)) / 12.0 + h.day / 365.0 - 1900) * 12.3685;
do {
mjd = tmoonphase(k--, 0);
} while (mjd > jd);
k--;
for(i = tmoonphase(k,0); i < tmoonphase(k+5,0 ); i++){
datemoon[i%200][0] = 0;
datemoon[i%200][1] = i;
}
for(j = 0; j < 6; j++){
for(i = 0; i < 4; i++){
mjd = tmoonphase(k, i);
datemoon[mjd%200][0] = i+1;
datemoon[mjd%200][1] = mjd;
}
k++;
}
if(datemoon[jd%200][1] == jd)
return datemoon[jd%200][0];
return 0;
}
int daysComp(struct icaltimetype d1, struct icaltimetype d2){
if(d1.year < d2.year)
return 1; /* d1 < d2 */
if(d1.year > d2.year)
return 2; /* d1 > d2 */
/* years are equal */
if(d1.month < d2.month)
return 1; /* d1 < d2 */
if(d1.month > d2.month)
return 2; /* d1 > d2 */
/* months are equal */
if(d1.day < d2.day)
return 1; /* d1 < d2 */
if(d1.day > d2.day)
return 2; /* d1 > d2 */
return 0; /* days are equal */
}
int daysEqual(struct icaltimetype d1, struct icaltimetype d2){
if(daysComp(d1, d2) == 0)
return 1;
return 0;
}
int daysLater(struct icaltimetype d1, struct icaltimetype d2){
if(daysComp(d1, d2) == 1)
return 1;
return 0;
}
int daysEarlier(struct icaltimetype d1, struct icaltimetype d2){
if(daysComp(d1, d2) == 2)
return 1;
return 0;
}
int daysLaterEqual(struct icaltimetype d1, struct icaltimetype d2){
if(daysComp(d1, d2) != 2)
return 1;
return 0;
}
int daysEarlierEqual(struct icaltimetype d1, struct icaltimetype d2){
if(daysComp(d1, d2) != 1)
return 1;
return 0;
}