وحدة:Calconv

من ويكيبيديا، الموسوعة الحرة

--[[
 * Hijri (Islamic) to/from Gregorian (Christian) date conversion library.
 *  Based on Nadim Shaikli work (ITL)
 *  2004, Arabeyes, 
 * (www.arabeyes.org - under LGPL license - see COPYING file)
]]

local p = {}

---- Absolute date of start of Islamic calendar (July 19, 622 Gregorian)
local GregorianEpoch	= 1;
local HijriEpoch	= 227015;


hdayname = { 'الإثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'الجمعة','السبت', 'الأحد'}
hmonth = { 'محرم',    'صفر',    'ربيع الأول',    'ربيع الثاني',    'جمادى الأولى',    'جمادى الآخرة',    'رجب' ,    'شعبان',    'رمضان',    'شوال',    'ذو القعدة',    'ذو الحجة' }
gmonth = {"يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"}

--/* Determine if Hijri passed-in year is a leap year */
function h_leapyear( year ) 
   --/* True if year is an Islamic leap year */

if( math.abs(((11 * year) + 14) % 30) < 11 ) then
      return(1);
   else
      return(0);
   end
end

--/* Determine the number of days in passed-in hijri month/year */
function h_numdays(month, year )
   --/* Last day in month during year on the Islamic calendar. */

   if (((month % 2) == 1) or ((month == 12) and h_leapyear(year))) then
      return(30);
   else
      return(29);
   end
end

----/* Determine Hijri absolute date from passed-in day/month/year */
function h_absolute( day, month, year)
   -----/* Computes the Islamic date from the absolute date. */
  
   return(day				-----/* days so far this month */
	  + (29 * (month - 1))		----/* days so far... */
	  + math.floor(month / 2)	----/* ...this year */
	  + (354 * (year - 1))		----/* non-leap days in prior years */
	  + math.floor((3 + (11 * year)) / 30)	----/* leap days in prior years */
	  + HijriEpoch - 1);		----/* days before start of calendar */
end


----/* Determine Hijri/Islamic date from passed-in Gregorian day/month/year    ie. Gregorian -> Hijri  */
function h_date(day, month, year )
   local  abs_date; 	
   local pre_epoch = 0; 	

   local cdate = {};

   ----/* Account for Pre-Epoch date correction, year 0 entry */
   if (year < 0) then
      year =year+1;
   end 

   abs_date = g_absolute(day, month, year); 

   ----/* Search forward/backward year by year from approximate year */
   if (abs_date < HijriEpoch) then
      cdate["year"] = 0;

      while (abs_date <= h_absolute(1, 1, cdate["year"])) do
	 cdate["year"] =cdate["year"] -1;
     end   
   else
      cdate["year"] = math.floor((abs_date - HijriEpoch - 1)/ 355);

      while (abs_date >= h_absolute(1, 1, cdate["year"]+1)) do
            cdate["year"]=cdate["year"]+1;
      end
   end


   --/* Search forward month by month from Muharram */
   cdate["month"] = 1;
   while (abs_date > h_absolute(
                         h_numdays(cdate["month"], cdate["year"])
                        ,cdate["month"],
                        cdate["year"])) do
      cdate["month"]=cdate["month"]+1;
   end

   cdate["day"] = abs_date - h_absolute(1, cdate["month"], cdate["year"]) + 1;

   --/* Account for Pre-Hijrah date correction, year 0 entry */
   if (cdate["year"] <= 0) then
      pre_epoch   = 1;
      cdate["year"] = ((cdate["year"] - 1) * -1);
   end

   --/* Set resulting values */
   if(pre_epoch ~= 0) then cdate["units"] = "B.H" ; else cdate["units"] = "A.H"; end
   cdate["weekday"]	= (math.abs(abs_date % 7));
   cdate["frm_numdays"]	= g_numdays(month, year);
   cdate["to_numdays"]	= h_numdays(cdate["month"], cdate["year"]);
   cdate["to_numdays2"]	= h_numdays((cdate["month"] + 1), cdate["year"]);

   
   return(cdate);
end



--/* Determine the number of days in passed-in gregorian month/year */

function g_numdays( month, year )
   local y
   y = math.abs(year);

   --/* Compute the last date of the month for the Gregorian calendar. */
   if( month ==2 )
   then
	 if ( (((y % 4) == 0) and ((y % 100) ~= 0)) or ((y % 400) == 0) ) then
	    return 29;
	 else
	    return(28);      
     end 
   end
   if (month ==2 or month ==6 or month ==9 or month ==11 ) then return(30); end
   return(31);
end


--/* Determine Gregorian absolute date from passed-in day/month/year */
function g_absolute(day, month, year)

    local N
    N = day;           --/* days this month */

   m = month - 1; 
   while(m>0) do
   --/* days in prior months this year */
      N = N + g_numdays(m, year);
      m = m-1;
   end

   return(N				         --/* days this year */
	  + 365 * (year - 1)		         --/* previous years days ignoring leap */
	  + math.floor((year - 1)/ 4)		 --/* Julian leap days before this year.. */
	  - math.floor((year - 1)/ 100)	         --/* ..minus prior century years... */
	  + math.floor((year - 1)/ 400));	 --/* ..plus prior years divisible by 400 */
end


--/* Determine Gregorian date from passed-in Hijri/Islamic day/month/year   ie. Hijri -> Gregorian */
function g_date(day, month, year )
  local cdate = {};
  local abs_date;
  local  pre_epoch = 0;

   --/* Account for Pre-Epoch date correction, year 0 entry */
   if (year < 0) then
      year=year +1;
   end
  
   abs_date = h_absolute(day, month, year);

   --/* Search forward year by year from approximate year */
   cdate["year"] = math.floor(abs_date/ 366);

   while (abs_date >= g_absolute(1, 1, cdate["year"]+1)) do
      cdate["year"] = cdate["year"] +1;
   end

   --/* Search forward month by month from January */
   cdate["month"] = 1;
   while (abs_date > g_absolute(g_numdays(cdate["month"], cdate["year"]),
				cdate["month"],
				cdate["year"])) do
      cdate["month"] = cdate["month"]+1;
   end

   cdate["day"] = abs_date - g_absolute(1, cdate["month"], cdate["year"]) + 1;

   --/* Account for Pre-Hijrah date correction, year 0 entry */
   if (cdate["year"] <= 0)
   then
      pre_epoch   = 1;
      cdate["year"] = ((cdate["year"] - 1) * -1);
   end

   --/* Set resulting values */
   if( pre_epoch ~= 0) then cdate["units"] = "B.C";else cdate["units"] = "A.D";  end;

   cdate["weekday"]	= (math.abs(abs_date % 7));
   cdate["frm_numdays"]	= h_numdays(month, year);
   cdate["to_numdays"]	= g_numdays(cdate["month"], cdate["year"]);
   cdate["to_numdays2"]	= g_numdays((cdate["month"] + 1), cdate["year"]);

   return(cdate);
end

function p.g2h(frame)
    local args = frame.args
    local year = 0
    local month = 0
    local day = 0
    local osdate = os.date('*t')

    day = tonumber(args['يوم'] or args[1] or osdate.day)
    month = tonumber (args['شهر'] or args[2] or osdate.month)
    year =  tonumber(args['سنة'] or args[3] or osdate.year)

   local r 
   r = h_date(day, month,year ) 
   return "[["..r["day"].." "..hmonth[r["month"]].."]] [["..r["year"].." هـ]]";
end


function p.h2g(frame)
    local args = frame.args
    local year = 0
    local month = 0
    local day = 0
    local osdate = os.date('*t')
   local r 

    day = tonumber(args['يوم'] or args[1] or osdate.day)
    month =  tonumber(args['شهر'] or args[2] or osdate.month)
    year =  tonumber(args['سنة'] or args[3] or osdate.year)

   r = g_date(day, month,year ) 
   return "[["..r["day"].." "..gmonth[r["month"]].."]] [["..r["year"].."]]";
end

return p