// JavaScript Document
/*********************************************************************************************************
                Additions to date object to include fubctionality for Arabic dates
*********************************************************************************************************/
/**new data members to store Arabic date,month and year*/
	Date.prototype.Arabyear=0;
	Date.prototype.Arabmonth=0;
	Date.prototype.Arabdate=0;

/**Array of errors in the algorithm for each month from 1420-1434*/
	Date._offset=new Array( new Array(0,0,0,0,0,0,0,0,0,0,0,0),
							new Array( 0,-1,0,-1,-1,-1,-1,-1,0,0,1,0), 
                        new Array( 0,-1,-1,-1,-1,-2,-2,-2,-1,-1,0,-1),
						new Array( 0,0,0,-1,0,-1,-1,-2,-1,-1,0,-1), 
						new Array( 0,0,0,0,0,0,0,-1,0,-1,0,-1), 
						new Array( -1,-1,-1,-1,0,-1,0,-1,-1,-1,-1,-1), 
						new Array( -1,-1,-1,-1,0,-1,0,-1,0,0,0,0), 
						new Array( 0,-1,0,-1,0,-1,0,0,0,0,1,0), 
						new Array( 0,-1,-1,-1,-1,-2,-1,-1,0,-1,0,0), 
						new Array( 0,0,0,-1,0,-1,-1,-1,0,0,0,0), 
						new Array( 0,-1,0,-1,-1,-1,-1,-2,-1,-1,-1,-1), 
						new Array( 0,-1,0,0,0,-1,0,-1,0,-1,0,-1), 
						new Array( 0,-1,0,0,0,0,0,0,0,0,0,-1), 
						new Array( -1,-2,-1,-1,0,-1,0,-1,0,-1,0,-1), 
						new Array( -1,-1,-1,-1,0,-1,0,0,0,0,0,0), 
						new Array( 0,-1,0,-1,0,-1,0,0,0,0,1,0),
						new Array(0,0,0,0,0,0,0,0,0,0,0,0));
Date.gdays=[31,31,28,31,30,31,30,31,31,30,31,30,31]	
/**returns the Day of the Arabic month (0-30)*/
Date.prototype.getArabDate =function()
{
  return(this.Arabdate);
};

/**returns the Arabic month  (0-11)*/
Date.prototype.getArabMonth = function()
{
  return(this.Arabmonth);
};

/**returns the Arabic year in 4 digits*/
Date.prototype.getArabYear = function()
{
  return(this.Arabyear);
};

/**Assigns the arabic date to another date object*/
Date.prototype.setArabValues=function(date)
{
	this.setArabYear(date.Arabyear);
	this.setArabMonth(date.Arabmonth);
	this.setArabDate(date.Arabdate);
}

/**Sets the day of the Arabic month*/
Date.prototype.setArabDate = function(d)
{
  var md=this.getMonthDays(this.Arabmonth+1);
  if(d>md)
  {
	this.setArabMonth(this.Arabmonth+1);
	this.Arabdate=d-md;
  }
  else if(d<1)
   {
	 this.setArabMonth(this.Arabmonth-1);
	 md=this.getMonthDays(this.Arabmonth+1);
	 this.Arabdate=md+d;
   }
   else
    this.Arabdate=d;
};

/**Sets the value of the Arabic month*/
Date.prototype.setArabMonth = function(m)
{
  if(m<1)
  {
    this.Arabmonth=12 + m;
	this.Arabyear=this.Arabyear-1;
  }
   else if(m>12)
   {
     this.Arabmonth=m-12 + 0;
	 this.Arabyear=eval(this.Arabyear)+eval(1);
   }
	else
	  this.Arabmonth=m;
};

/**sets the value of the Arabic year*/
Date.prototype.setArabYear=function(y)
{
  this.Arabyear=y;
};

/**returns the day of the week for the Arabic date*/
Date.prototype.getArabDay = function()
{
  var dat=new Date();	
  dat=this.ArabToGreg(this.Arabdate,this.Arabmonth+1,this.Arabyear);
  wd=dat.getDay();
  return wd;
};
Date.prototype.intPart = function(floatNum)
{
if (floatNum< -0.0000001)
	 return Math.ceil(floatNum-0.0000001);
else
     return Math.floor(floatNum+0.0000001);	
};

/**function that converts a Gregorian date to the Arabic date*/
Date.prototype.GregToArab = function(d,m,y) 
{
var Arabdate=new Date();
var temp=new Date();
if ((y>1582)||((y==1582)&&(m>10))||((y==1582)&&(m==10)&&(d>14)))
{
	jd=this.intPart((1461*(y+4800+this.intPart((m-14)/12)))/4)+this.intPart((367*(m-2-12*(this.intPart((m-14)/12))))/12)-
	this.intPart( (3* (this.intPart(  (y+4900+    this.intPart( (m-14)/12)     )/100)    )   ) /4)+d-32075;
}
else
{
	jd = 367*y-this.intPart((7*(y+5001+this.intPart((m-9)/7)))/4)+this.intPart((275*m)/9)+d+1729777;
}
l=jd-1948440+10632;
n=this.intPart((l-1)/10631);
l=l-10631*n+354;
j=(this.intPart((10985-l)/5316))*(this.intPart((50*l)/17719))+(this.intPart(l/5670))*(this.intPart((43*l)/15238));
l=l-(this.intPart((30-j)/15))*(this.intPart((17719*j)/50))-(this.intPart(j/16))*(this.intPart((15238*j)/43))+29;
am=this.intPart((24*l)/709);
ad=l-this.intPart((709*am)/24);
ay=30*n+j-30;
if(ay>=1420 && ay<=1450){
Arabdate.setArabYear(ay);
//The code below is to account for the error in the algorithm
month_days=Arabdate.getMonthDays(am);
error=Date._offset[ay-1419][am-1]; 
if(am==12)
 next_error=Date._offset[ay-1419+1][0];
else 
 next_error=Date._offset[ay-1419][am];
if(next_error<0 && ad-next_error>month_days && error<0)
       error=next_error;
if(ad-error>month_days && error<0)
{
   error=month_days-ad+error;
   ad=0;
   if(am==12)
     {am=1; ay++;}
   else	
     am++;
	 
}   
if(ad-error<1 && error>0)
{
   error=ad-error;
   if(am==1){
     temp.setArabYear(ay-1);
     prev_month_days=temp.getMonthDays(12);}
   else{
	temp.setArabYear(ay);
	prev_month_days=temp.getMonthDays(am-1);}
	ad=prev_month_days + 1;
   if(am==1)
     {am=12;ay--;}
   else	 
     am--;
}   
}
else
  error=0;
ad=ad-error; 
Arabdate.setArabMonth(am);Arabdate.setArabYear(ay);Arabdate.setArabDate(ad); 
return Arabdate;
};

/**function that converts an Arabic date to the Gregorian date*/
Date.prototype.ArabToGreg = function (d,m,y) 
{	
jd=this.intPart((11*y+3)/30)+354*y+30*m-this.intPart((m-1)/2)+d+1948440-385;
if (jd> 2299160 )
{
	 l=jd+68569;
	 n=this.intPart((4*l)/146097);
	l=l-this.intPart((146097*n+3)/4);
	 i=this.intPart((4000*(l+1))/1461001);
	l=l-this.intPart((1461*i)/4)+31;
	 j=this.intPart((80*l)/2447);
	gd=l-this.intPart((2447*j)/80);
	l=this.intPart(j/11);
	gm=j+2-12*l;
	gy=100*(n-49)+i+l;
}	
else	
{
	 j=jd+1402;
	 k=this.intPart((j-1)/1461);
	 l=j-1461*k;
	 n=this.intPart((l-1)/365)-this.intPart(l/1461);
	 i=l-365*n+30;
	 j=this.intPart((80*i)/2447);
	gd=i-this.intPart((2447*j)/80);
	i=this.intPart(j/11);
	gm=j+2-12*i;
	gy=4*k+n+i-4716;
}
 var Gregdate=new Date(gy,gm-1,gd);
 if(y>=1420 && y<=1434)
   error=Date._offset[y-1419][m-1];
 else
    error=0;
 Gregdate.setDate(Gregdate.getDate()+error);
 return Gregdate;
};

/**calculates and returns the number of days in the Arab month (29-30)*/
Date.prototype.getMonthDays = function (month) 
{
	var year = this.getArabYear();
	greg_curr=this.ArabToGreg(1,month,year);
	greg_year=greg_curr.getFullYear();
	greg_month=greg_curr.getMonth();
	if(month==12)
       greg_next=this.ArabToGreg(1,1,year+1);
	else
        greg_next=this.ArabToGreg(1,month+1,year);
    if (((0 == (greg_year%4)) && ( (0 != (greg_year%100)) || (0 == (greg_year%400)))) && greg_month == 1)
	{
		greg_month_days=29;
	} 
	else 
	{
		greg_month_days=Date.gdays[greg_month+1];
	}
	 if(greg_curr.getMonth()==greg_next.getMonth())
	   month_days=greg_next.getDate()-greg_curr.getDate();
	 else if((greg_next.getMonth()-greg_curr.getMonth())==2)
	   {
	      curr_month_days=Date.gdays[greg_curr.getMonth()+1];
		  next_month_days=Date.gdays[greg_curr.getMonth()+2];
		  return(curr_month_days-greg_curr.getDate()+next_month_days+greg_next.getDate());
		}  
	 else  
       month_days=greg_month_days-greg_curr.getDate()+greg_next.getDate();
 return(month_days);
};

