HOWTO: Convert Dates Between Gregorian and Hijri Calendar

ID: Q224353


The information in this article applies to:
  • Microsoft Windows 98
  • Microsoft Windows 95


SUMMARY

In the Arabic Localized version of Windows 95 and Windows 98, you can convert a Hijri date from a Gregorian date, but you cannot convert a Gregorian date from a Hijri date. This article shows you how to do this using the Windows API GetDateFormat function.


MORE INFORMATION

The GetDateFormat function converts a Hijri Date from a supplied Gregorian date, but it cannot convert a Gregorian date from a Hijri date. The reason for this is it's non-deterministic; that is, it depends on the locale and whether the Advanced Hijri Date feature has been used before. The Gregorian to Hijri dates are converted because the conversion is valid for that particular client.

Developers need to implement this capability themselves. The following code allows you to convert from Hijri to Gregorian and from Gregorian to Hijri.


// date.cpp : Defines the initialization routines for the DLL.
// 
typedef unsigned char       BYTE;
typedef struct tagDATEINFO {
	BYTE			dtDay;      
	BYTE 			dtMonth;    
	unsigned short	dtYear;     
} DATEINFO;

void ConvertGregDateToHijri(DATEINFO *, DATEINFO *);
void ConvertHijriDateToGreg(DATEINFO *, DATEINFO *);

// 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(DATEINFO *pDGreg, DATEINFO *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(DATEINFO *pDHijri, DATEINFO *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);
} 

Additional query words: Hijri, Gregorian, Calendar, Arabic,

Keywords : kbBidi kbNLS kbWinOS98 kbLocalization
Version : WINDOWS:
Platform : WINDOWS
Issue type : kbhowto


Last Reviewed: December 20, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.