Friday, February 22, 2008

الگوریتم تبدیل تاریخ میلادی به هجری قمری و بالعکس

typedef unsigned char BYTE;

typedef struct tagDATE11 {

BYTE dtDay;

BYTE dtMonth;

unsigned short dtYear;

} DATE1;

void ConvertGregDateToHijri(DATE1 *, DATE1 *);

void ConvertHijriDateToGreg(DATE1 *, DATE1 *);

// Converts a Hijri M to # of days

static long HM2Days(long m)

{

long mdays[13] = {0,30,59,89,118,148,177,207,236,266,295,325,355};

return (mdays[m-1]);

}

// Returns 1 if Gregorian year is a leap year

static long IsGYLeap(long y)

{

return ((y%4 == 0) && ((y%100 > 0) || (y%400 == 0)));

}

// Converts a Gregorian M to # of days

static long GM2Days(long m)

{

long mdays[13] = {0,31,59,90,120,151,181,212,243,273,304,334,365};

return mdays[m-1];

}

// Returns total # of days for a Gregorian year

static long GY2nDays(long y)

{

y = y - 1;

return (y*365L + y/4 - y/100 + y/400);

}

// Returns 1 if hijri year is a leap year

static long IsHYLeap(long y)

{

long mdays[11]={2,5,7,10,13,15,18,21,24,26,29};

long i;

y %= 30;

for (i=0; i<11; i++)

{

if (y == mdays[i])

return 1;

}

return 0;

}

// Returns total # of days for a Hijri year

static long HY2nDays(long y)

{

long y30, yleft;

long result;

y30 = ((y-1) / 30) * 30;

yleft = y - y30 - 1;

result = ((y30 * 10631L) / 30L) + 227013L;

while (yleft)

result += 354L + IsHYLeap(yleft--);

return result;

}

// Returns Hijri year for a total # of days

static long nDays2HY(long d)

{

long hy = (((d - 227013L) * 30L / 10631L) + 1);

if (d <= HY2nDays(hy))

hy--;

else if (d > HY2nDays(hy+1))

hy++;

return hy;

}

// Returns the Hijri month number corresponding to a certain number of days

static long nDays2HM(long ndays)

{

long i = 1;

long d = (ndays - HY2nDays(nDays2HY(ndays)));

while (d > HM2Days(i))

i++;

return (i - 1);

}

// Converts # of days to a Gregorian year

static long nDays2GY(long days)

{

long d = (days * 400L / 146097L);

if (days > GY2nDays(d+2))

return (d+2);

else if (days > GY2nDays(d+1))

return (d+1);

else

return (d);

}

// Returns 1 if the number of days corresponds to a leap Gregorian year

static long IsnDaysLeap(long days)

{

long y = nDays2GY(days);

return (IsGYLeap(y) && (days - GY2nDays(y) > 59));

}

// Returns the Gregorian month number corresponding to a certain number of days

static long nDays2GM(long ndays)

{

long i = 1;

long d = (ndays - GY2nDays(nDays2GY(ndays)) - IsnDaysLeap(ndays));

while (d > GM2Days(i))

i++;

return (i - 1);

}

// Returns the Hijri day corresponding to a certain number of days

static long nDays2HD(long ndays)

{

return (ndays - HY2nDays(nDays2HY(ndays)) - HM2Days(nDays2HM(ndays)));

}

// Converts a hijri M/D/Y to total # of days

static long HDMY2nDays(long d, long m, long y)

{

return (HY2nDays(y) + HM2Days(m) + d);

}

// Converts a Gregorian M/D/Y to total # of days

static long GDMY2nDays(long d, long m, long y)

{

return ((IsGYLeap(y) && (m > 2)) + GY2nDays(y) + GM2Days(m) + d);

}

// returns the Gregorian day corresponding to a certain number of

static long nDays2GD(long ndays)

{

return (ndays - GDMY2nDays(1, nDays2GM(ndays), nDays2GY(ndays)) + 1);

}

//Convert Gregorian Date to Hijri Date

void ConvertGregDateToHijri(DATE1 *pDGreg, DATE1 *pDHijri)

{

long lDate;

ASSERT( pDHijri && pDGreg );

lDate = GDMY2nDays((long)pDGreg->dtDay, (long)pDGreg->dtMonth, (long)pDGreg->dtYear);

pDHijri->dtMonth = (BYTE)nDays2HM(lDate);

pDHijri->dtYear = (unsigned short)nDays2HY(lDate);

pDHijri->dtDay = (BYTE)nDays2HD(lDate);

}

//Convert Hijri Date to Gregorian

void ConvertHijriDateToGreg(DATE1 *pDHijri, DATE1 *pDGreg)

{

long lDate = 0, x = 0;

ASSERT( pDHijri && pDGreg );

lDate = HDMY2nDays((long)pDHijri->dtDay, (long)pDHijri->dtMonth, (long)pDHijri->dtYear);

pDGreg->dtDay = (BYTE)nDays2GD(lDate);

pDGreg->dtMonth = (BYTE)nDays2GM(lDate);

pDGreg->dtYear = (unsigned short)nDays2GY(lDate);

}

با تشکر

هاشمی - زمستان 1386