[sourcecode languange=”cpp”]
/************************************************************************
* $Id: umm_alqura.c,v 1.5 2004/07/16 01:16:32 nadim Exp $
*
* ————
* Description:
* ————
* Copyright (c) 2004, Arabeyes, Fayez Alhargan
*
* This is a program that computes the Hijary dates for Umm-AlQura
* calendar the official calendar of the Kingdom of Saudi Arabia.
*
* King Abdulaziz City for Science and Technology
* Computer and Electronics Research Institute
* Riyadh, Saudi Arabia
* alhargan-at-kacst.edu.sa
* Tel:4813770 Fax:4813764
*
* Fayez Alhargan version: opn1.2
* Fayez Alhargan last modified 22-1-2003
*
* —————–
* Revision Details: (Updated by Revision Control System)
* —————–
* $Date: 2004/07/16 01:16:32 $
* $Author: nadim $
* $Revision: 1.5 $
* $Source$
*
* (www.arabeyes.org – under LGPL license – see COPYING file)
************************************************************************/</pre>
[/sourcecode]
[sourcecode languange=”cpp”]
#include <stdlib.h>
#include <math.h>
#include "hijri.h"
#define HStartYear 1420
#define HEndYear 1450
extern char *g_day[7];
extern char *h_day[7];
extern char *g_day_short[7];
extern char *h_day_short[7];
extern char *g_month[13];
extern char *h_month[13];
extern char *g_month_short[13];
extern char *h_month_short[13];
int MonthMap[]={19410,
19396,19337,19093,13613,13741,15210,18132,19913,19858,19110,
18774,12974,13677,13162,15189,19114,14669,13469,14685,12986,
13749,17834,15701,19098,14638,12910,13661,15066,18132,18085
};
/* makes it circular m[0]=m[12] & m[13]=m[1] */
short gmonth[14]={31,31,28,31,30,31,30,31,31,30,31,30,31,31};
/* makes it circular m[0]=m[12] & m[13]=m[1] */
short smonth[14]={31,30,30,30,30,30,29,31,31,31,31,31,31,30};
/* Various Prototypes */
int G2H(sDate *mydate, int dg, int mg, int yg);
int H2G(sDate *mydate, int dh, int mh, int yh);
int Hsub2G(sDate *mydate, int mh, int yh);
double GCalendarToJD(int yg, int mg, double dg );
double JDToGCalendar(double JD, sDate *mydate);
int GLeapYear(int year);
void GDateAjust(sDate *mydate);
int DayWeek(long JulianD);
void JDToHCalendar(double JD, sDate *mydate);
void JDToHACalendar(double JD, int *yh, int *mh, int *dh);
double HCalendarToJD(int yh, int mh, int dh);
double HCalendarToJDA(int yh, int mh, int dh);
int HMonthLength(int yh, int mh);
double ip(double x);
int mod(double x, double y);
int IsValid(int yh, int mh, int dh);
/****************************************************************************/
/* Name: Hsub2G */
/* Type: Procedure */
/* Purpose: Finds Gdate(year,month,day) for Hdate(year,month,day) */
/* Arguments: */
/* Input: Hijri date: year:yh, month:mh */
/* Output: Gregorian date: year:yg, month:mg, day:dg , day of week:dayweek */
/* and returns flag found:1 not found:0 */
/****************************************************************************/
int Hsub2G(sDate *mydate, int mh, int yh)
{
int flag;
long JD;
double GJD;
/* Make sure that the date is within the range of the tables */
if(mh < 1) {mh = 12;}
if(mh > 12) {mh = 1;}
if(yh < HStartYear) {yh = HStartYear;}
if(yh > HEndYear) {yh = HEndYear;}
GJD = HCalendarToJDA(yh, mh, 1);
JDToGCalendar(GJD, mydate);
JD = (long) GJD;
mydate->weekday = (JD + 1) % 7;
/* NOTE: so when is flag = 0 ? */
flag = 1; /* date has been found */
return(flag);
}
/****************************************************************************/
/* Name: HCalendarToJDA */
/* Type: Function */
/* Purpose: convert Hdate(year,month,day) to Exact Julian Day */
/* Arguments: */
/* Input : Hijrah date: year:yh, month:mh, day:dh */
/* Output: The Exact Julian Day: JD */
/****************************************************************************/
double HCalendarToJDA(int yh, int mh, int dh)
{
int flag, Dy, m, b;
long JD;
double GJD;
/* estimate JD of the beginning of year */
JD = (long) HCalendarToJD(yh, 1, 1);
Dy = MonthMap[yh-HStartYear]/4096; /* Mask 1111000000000000 */
GJD = JD – 3 + Dy; /* correct the JD value from stored tables */
b = MonthMap[yh – HStartYear];
b = b – Dy * 4096;
for(m=1; m < mh; m++)
{
flag = b % 2; /* Mask for the current month */
if(flag)
Dy = 30;
else
Dy = 29;
GJD = GJD + Dy; /* Add the months lengths before mh */
b = (b – flag) / 2;
}
GJD = GJD + dh – 1;
return(GJD);
}
/****************************************************************************/
/* Name: HMonthLength */
/* Type: Function */
/* Purpose: Obtains the month length */
/* Arguments: */
/* Input : Hijrah date: year:yh, month:mh */
/* Output: Month Length */
/****************************************************************************/
int HMonthLength(int yh, int mh)
{
int flag, Dy, m, b;
if(yh<HStartYear || yh>HEndYear)
{
flag = 0;
Dy = 0;
}
else
{
Dy = MonthMap[yh – HStartYear]/4096; /* Mask 1111000000000000 */
b = MonthMap[yh – HStartYear];
b = b – Dy * 4096;
for(m=1; m <= mh; m++)
{
flag = b % 2; /* Mask for the current month */
if(flag)
Dy = 30;
else
Dy = 29;
b = (b – flag) / 2;
}
}
return(Dy);
}
/****************************************************************************/
/* Name: DayInYear */
/* Type: Function */
/* Purpose: Obtains the day number in the yea */
/* Arguments: */
/* Input : Hijrah date: year:yh, month:mh day:dh */
/* Output: Day number in the Year */
/****************************************************************************/
int DayinYear(int yh, int mh, int dh)
{
int flag, Dy, m, b, DL;
if(yh<HStartYear || yh>HEndYear)
{
flag = 0;
DL = 0;
}
else
{
Dy = MonthMap[yh – HStartYear]/4096; /* Mask 1111000000000000 */
b = MonthMap[yh – HStartYear];
b = b – Dy * 4096;
DL = 0;
for(m = 1; m <= mh; m++)
{
flag = b % 2; /* Mask for the current month */
if(flag)
Dy = 30;
else
Dy = 29;
b = (b – flag) / 2;
DL = DL + Dy;
}
DL = DL + dh;
}
return(DL);
}
/****************************************************************************/
/* Name: HYearLength */
/* Type: Function */
/* Purpose: Obtains the year length */
/* Arguments: */
/* Input : Hijrah date: year:yh */
/* Output: Year Length */
/****************************************************************************/
int HYearLength(int yh)
{
int flag, Dy, m, b, YL;
if(yh<HStartYear || yh>HEndYear)
{
flag = 0;
YL = 0;
}
else
{
Dy = MonthMap[yh – HStartYear]/4096; /* Mask 1111000000000000 */
b = MonthMap[yh – HStartYear];
b = b – Dy * 4096;
flag = b % 2; /* Mask for the current month */
if(flag)
YL = 30;
else
YL = 29;
for(m = 2; m <= 12; m++)
{
flag = b % 2; /* Mask for the current month */
if(flag)
Dy = 30;
else
Dy = 29;
b = (b – flag) / 2;
YL = YL + Dy;
}
}
return(YL);
}
/****************************************************************************/
/* Name: G2H */
/* Type: Procedure */
/* Purpose: convert Gdate(year,month,day) to Hdate(year,month,day) */
/* Arguments: */
/* Input: Gregorian date: year:yg, month:mg, day:dg */
/* Output: Hijrah date: year:yh, month:mh, day:dh, day of week:dayweek */
/* and returns flag found:1 not found:0 */
/****************************************************************************/
int G2H(sDate *mydate, int dg, int mg, int yg)
{
int yh2, mh2;
int df;
int flag = 1;
long J;
double GJD, HJD;
sDate tmpdate;
sDate tmpdate2;
int error_fill;
GJD = GCalendarToJD(yg, mg, dg + 0.5); /* find JD of Gdate */
/* estimate the Hdate that correspond to the Gdate */
JDToHCalendar(GJD, &tmpdate);
/* get the exact Julian Day */
HJD = HCalendarToJDA(tmpdate.year, tmpdate.month, tmpdate.day);
df = (int) (GJD – HJD);
tmpdate.day += df;
while(tmpdate.day > 30)
{
tmpdate.day -= HMonthLength(tmpdate.year, tmpdate.month);
tmpdate.month++;
if(tmpdate.month > 12)
{
tmpdate.year++;
tmpdate.month = 1;
}
}
if(tmpdate.day == 30)
{
yh2 = tmpdate.year;
mh2 = tmpdate.month + 1;
if(mh2 > 12)
{
yh2++;
mh2 = 1;
}
Hsub2G(&tmpdate2, mh2, yh2);
/* Make sure that the month is 30days if not make adjustment */
if(dg == tmpdate2.day)
{
tmpdate.year = yh2;
tmpdate.month = mh2;
tmpdate.day = 1;
}
}
J = (long) (GCalendarToJD(yg, mg, dg)+2);
mydate->weekday = J % 7;
mydate->to_numdays = 1; /* this needs to be fixed !! */
mydate->year = tmpdate.year;
mydate->month = tmpdate.month;
mydate->day = tmpdate.day;
/* Fill-in the structure with various nicities a user might need */
error_fill = fill_datestruct(mydate, mydate->weekday, mg, mydate->month,
g_day, g_day_short, g_month, g_month_short,
h_day, h_day_short, h_month, h_month_short,
NULL, 0);
// h_events_table, sizeof(h_events_table));
return(flag);
}
/****************************************************************************/
/* Name: H2G */
/* Type: Procedure */
/* Purpose: convert Hdate(year,month,day) to Gdate(year,month,day) */
/* Arguments: */
/* Input/Ouput: Hijrah date: year:yh, month:mh, day:dh */
/* Output: Gregorian date: year:yg, month:mg, day:dg , day of week:dayweek */
/* and returns flag found:1 not found:0 */
/* Note: The function will correct Hdate if day=30 and the month is 29 only */
/****************************************************************************/
int H2G(sDate *mydate, int dh, int mh, int yh)
{
int found, yh1, mh1;
int error_fill;
sDate tmpdate;
/* make sure values are within the allowed values */
if(dh > 30) { dh = 1; mh++; }
if(dh < 1) { dh = 1; mh–; }
if(mh > 12) { mh = 1; yh++; }
if(mh < 1) { mh = 12; yh–; }
/* find the date of the begining of the month */
found = Hsub2G(mydate, mh, yh);
mydate->day += dh – 1;
/* Make sure that dates are within the correct values */
GDateAjust(mydate);
mydate->weekday += dh – 1;
mydate->weekday = mydate->weekday % 7;
/*find the date of the begining of the next month*/
if(dh == 30)
{
mh1 = mh + 1;
yh1 = yh;
if(mh1 > 12) {mh1 -= 12; yh1++;}
found = Hsub2G(&tmpdate, mh1, yh1);
/* Make sure that the month is 30days if not make adjustment */
if(mydate->day == tmpdate.day)
{
mydate->year = tmpdate.year;
mydate->month = tmpdate.month;
mydate->day = 1;
}
}
/* Fill-in the structure with various nicities a user might need */
error_fill = fill_datestruct(mydate, mydate->weekday, mh, mydate->month,
h_day, h_day_short, h_month, h_month_short,
g_day, g_day_short, g_month, g_month_short,
NULL, 0);
// g_events_table, sizeof(g_events_table));
return(found);
}
/****************************************************************************/
/* Name: JDToGCalendar */
/* Type: Procedure */
/* Purpose: convert Julian Day to Gdate(year,month,day) */
/* Arguments: */
/* Input: The Julian Day: JD */
/* Output: Gregorian date: year:yy, month:mm, day:dd */
/****************************************************************************/
double JDToGCalendar(double JD, sDate *mydate)
{
double A, B, F;
int alpha, C, E;
long D, Z;
Z = (long)floor (JD + 0.5);
F = (JD + 0.5) – Z;
alpha = (int)((Z – 1867216.25) / 36524.25);
A = Z + 1 + alpha – alpha / 4;
B = A + 1524;
C = (int) ((B – 122.1) / 365.25);
D = (long) (365.25 * C);
E = (int)(((B – D) / 30.6001));
mydate->day =(int) (B – D – floor (30.6001 * E) + F);
if (E < 14)
mydate->month = E – 1;
else
mydate->month = E – 13;
if (mydate->month > 2)
mydate->year = C – 4716;
else
mydate->year = C – 4715;
F = F * 24.0;
return(F);
}
/****************************************************************************/
/* Name: GCalendarToJD */
/* Type: Function */
/* Purpose: convert Gdate(year,month,day) to Julian Day */
/* Arguments: */
/* Input : Gregorian date: year:yy, month:mm, day:dd */
/* Output: The Julian Day: JD */
/****************************************************************************/
double GCalendarToJD(int yy, int mm, double dd)
{
/* It does not take care of 1582 correction assumes correct
calender from the past
*/
int A, B, m, y;
double T1, T2, Tr;
if (mm > 2)
{
y = yy;
m = mm;
}
else
{
y = yy – 1;
m = mm + 12;
}
A = y / 100;
B = 2 – A + A / 4;
T1=ip (365.25 * (y + 4716));
T2=ip (30.6001 * (m + 1));
Tr=T1+ T2 + dd + B – 1524.5 ;
return(Tr);
}
/****************************************************************************/
/* Name: GLeapYear */
/* Type: Function */
/* Purpose: Determines if Gdate(year) is leap or not */
/* Arguments: */
/* Input : Gregorian date: year */
/* Output: 0:year not leap 1:year is leap */
/****************************************************************************/
int GLeapYear(int year)
{
int T = 0;
if(year % 4 == 0)
T = 1; /* leap_year = 1; */
if(year % 100 == 0)
{
/* years=100,200,300,500,… are not leap years */
T=0;
/* years=400,800,1200,1600,2000,2400 are leap years */
if(year % 400 == 0) T = 1;
}
return(T);
}
/****************************************************************************/
/* Name: GDateAjust */
/* Type: Procedure */
/* Purpose: Adjust the G Dates by making sure that the month lengths */
/* are correct if not so take the extra days to next month or year */
/* Arguments: */
/* Input: Gregorian date: year:yg, month:mg, day:dg */
/* Output: corrected Gregorian date: year:yg, month:mg, day:dg */
/****************************************************************************/
void GDateAjust(sDate *mydate)
{
int dys;
/* Make sure that dates are within the correct values */
/* Underflow */
if(mydate->month < 1) /* months underflow */
{
/* plus as the underflow months is negative */
mydate->month += 12;
mydate->year–;
}
if(mydate->day < 1) /* days underflow */
{
/* month becomes the previous month */
mydate->month–;
/* number of days of the month less the underflow days
(it is plus as the sign of the day is negative)
*/
mydate->day += gmonth[mydate->month];
if(mydate->month == 2)
mydate->day += GLeapYear(mydate->year);
if(mydate->month < 1) /* months underflow */
{
/* plus as the underflow months is negative */
mydate->month += 12;
mydate->year–;
}
}
/* Overflow */
if(mydate->month > 12) /* months */
{
mydate->month -= 12;
mydate->year++;
}
if(mydate->month == 2)
/* number of days in the current month */
dys = gmonth[mydate->month] + GLeapYear(mydate->year);
else
dys = gmonth[mydate->month];
if(mydate->day > dys) /* days overflow */
{
mydate->day -= dys;
mydate->month++;
if(mydate->month == 2)
{
/* number of days in the current month */
dys = gmonth[mydate->month] + GLeapYear(mydate->year);
if(mydate->day > dys)
{
mydate->day -= dys;
mydate->month++;
}
}
if(mydate->month > 12) /* months */
{
mydate->month -= 12;
mydate->year++;
}
}
mydate->to_numdays = dys;
}
/****************************************************************************/
/*
The day of the week is obtained as
Dy=(Julian+1)%7
Dy=0 Sunday
Dy=1 Monday
…
Dy=6 Saturday
*/
/****************************************************************************/
int DayWeek(long JulianD)
{
int Dy;
Dy = (JulianD + 1) % 7;
return(Dy);
}
/****************************************************************************/
/* Name: HCalendarToJD */
/* Type: Function */
/* Purpose: convert Hdate(year,month,day) to estimated Julian Day */
/* Arguments: */
/* Input : Hijrah date: year:yh, month:mh, day:dh */
/* Output: The Estimated Julian Day: JD */
/****************************************************************************/
double HCalendarToJD(int yh, int mh, int dh)
{
/* Estimating The JD for hijrah dates
this is an approximate JD for the given hijrah date
*/
double md, yd;
md = (mh – 1.0) * 29.530589;
yd = (yh – 1.0) * 354.367068 + md + dh – 1.0;
yd = yd + 1948439.0; /* add JD for 18/7/622 first Hijrah date */
return(yd);
}
/****************************************************************************/
/* Name: JDToHCalendar */
/* Type: Procedure */
/* Purpose: convert Julian Day to estimated Hdate(year,month,day) */
/* Arguments: */
/* Input: The Julian Day: JD */
/* Output : Hijrah date: year:yh, month:mh, day:dh */
/****************************************************************************/
void JDToHCalendar(double JD, sDate *mydate)
{
/* Estimating the hijrah date from JD */
double md, yd;
yd = JD-1948439.0; /* subtract JD for 18/7/622 first Hijrah date*/
md = mod(yd, 354.367068);
mydate->day = mod(md + 0.5, 29.530589)+1;
mydate->month = (int) ((md/29.530589) + 1);
yd = yd – md;
mydate->year = (int) (yd/354.367068 + 1);
if(mydate->day > 30) {mydate->day -= 30; mydate->month++;}
if(mydate->month > 12) {mydate->month -= 12; mydate->year++;}
}
/****************************************************************************/
/* Name: JDToHACalendar */
/* Type: Procedure */
/* Purpose: convert Julian Day to Hdate(year,month,day) */
/* Arguments: */
/* Input: The Julian Day: JD */
/* Output : Hijrah date: year:yh, month:mh, day:dh */
/****************************************************************************/
void JDToHACalendar(double JD, int *yh, int *mh, int *dh)
{
int df;
long J;
double HJD;
sDate tmpdate;
/* Estimate the Hdate that correspond to the Gdate */
JDToHCalendar(JD, &tmpdate);
/* get the exact Julian Day */
HJD = HCalendarToJDA(tmpdate.year, tmpdate.month, tmpdate.day);
df = (int) (JD + 0.5 – HJD);
tmpdate.day += df;
while(tmpdate.day > 30)
{
tmpdate.day -= HMonthLength(tmpdate.year, tmpdate.month);
tmpdate.month++;
if(tmpdate.month > 12)
{
tmpdate.year++;
tmpdate.month = 1;
}
}
if(tmpdate.day == 30 &&
HMonthLength(tmpdate.year, tmpdate.month) < 30)
{
tmpdate.day = 1;
tmpdate.month++;
}
if(tmpdate.month > 12)
{
tmpdate.month = 1;
tmpdate.year++;
}
/*
J = JD + 2;
*dayweek = J % 7;
*/
*yh = tmpdate.year;
*mh = tmpdate.month;
*dh = tmpdate.day;
}
/**************************************************************************/
/* Purpose: return the integral part of a double value. */
/**************************************************************************/
double ip(double x)
{
double tmp;
modf(x, &tmp);
return(tmp);
}
/**************************************************************************/
/* Name: mod */
/* Purpose: The mod operation for doubles x mod y */
/**************************************************************************/
int mod(double x, double y)
{
int r;
double d;
d = x / y;
r = (int) d;
if(r < 0)
r–;
d = x – y * r;
r = (int) d;
return(r);
}
/**************************************************************************/
/* Purpose: returns 0 for incorrect Hijri date and 1 for correct date */
/**************************************************************************/
int IsValid(int yh, int mh, int dh)
{
int valid = 1;
if((yh < HStartYear) || (yh > HEndYear))
valid = 0;
if( (mh < 1) || (mh > 12))
valid = 0;
if( (dh < 1) || (dh > HMonthLength(yh, mh)) )
valid = 0;
return(valid);
}
[/sourcecode]
Leave a Reply