وحدة:Hijri/Calendar

من ويكي مصدر، المكتبة الحرة
local cfg= mw.loadData('Module:Hijri/Configuration')
local core = require 'Module:Hijri/core'
--[[ ----------------- I M P O R T --------------]]
gregorian2jd = core.gregorian2jd
jd2hijri = core.jd2hijri
hijri2jd = core.hijri2jd
hijri_days_in_month = core.hijri_days_in_month
hijri_isleap = core.hijri_isleap
hijri_yday = core.hijri_yday
jd2unix = core.jd2unix
unix2jd = core.unix2jd
jd2wday = core.jd2wday
jd2gregorian = core.jd2gregorian
gre_isleap = core.gre_isleap
gre_yday = core.gre_yday
gre_days_in_month = core.gre_days_in_month
jd2julian = core.jd2julian
julian2jd = core.julian2jd
julian_isleap = core.julian_isleap
julian_yday = core.julian_yday
julian_days_in_month = core.julian_days_in_month
gregorian2hijri = core.gregorian2hijri
hijri2gregorian = core.hijri2gregorian
Date = core.Date
hijri_check = core.hijri_check
string = mw.ustring
local str_hijri_mode = select(cfg.hijri_mode + 1, 'hijri_tabular', 'hijri_adjusted_umalqura', 'hijri_umalqura')
local use_mashreq_numbers=false
--[[---------------------- utilty function ----------------- ]]
local gtonumber = tonumber

local function tonumber(str)
	if not str then
		return nil
	end
	local thenumber = gtonumber(str) or mw.language.getContentLanguage():parseFormattedNumber(str)
	if not thenumber then
		return nil
	end
	return math.floor(thenumber)
end
local function substitute( msg, args )
	return args and mw.message.newRawMessage( msg, args ):plain() or msg;
end

local function error( msg, args )
	return substitute( cfg.presentation.error, substitute( msg, args ) );
end

local function towdigit(number)
	return ((number<10) and '0' or '') .. number
end

local function hijri_month_name(index)
	local month_name
	if cfg.hijri_months then
		return cfg.hijri_months[index]
	else
		return mw.message.new('hijri-calendar-m' .. index):plain()
	end
end

local function hijri_short_month(index)
	if cfg.hijri_short_months then
		return cfg.hijri_short_months[index]
	end
end

local function wday_name(index)
	if cfg.wday_name then
		return cfg.wday_name[index]
	else
		return mw.message.new(select(index +1 ,'Sunday','Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday')):plain()
	end
end
local function wday_reindex(index)
	return (index<6) and (index+1) or 0
end

local function julian_month_name(index)
	if cfg.gregorian_months then
		return cfg.gregorian_months[index]
	else
		return mw.message.new(select(index, 'january', 'february', 'march', 'april', 'may_long', 'june', 'july', 'august', 'september', 'october', 'november', 'december')):plain()
	end
end

local function month_name(cal, index)
	if index>12 then
		index=index-12
	end
	
	if index<1 then
		index=index+12
	end

	if cal=='hijri' then
		return hijri_month_name(index)
	else
		return julian_month_name(index)
	end
end

local format_func = {
	towdigit = towdigit,
	hijri_month_name = hijri_month_name,
	wday_name = wday_name,
	julian_month_name = julian_month_name
}

local function substitute( msg, args )
	return args and mw.message.newRawMessage( msg, args ):plain() or msg;
end

local function error( msg, args )
	return substitute( cfg.presentation.error,  substitute( msg, args ) );
end


local function argument_wrapper(arg)
	local nilargs = {}
	return setmetatable({},
	{
		__index = function ( tbl, k )
			local v = rawget(tbl,k)
			if v then
				return v
			elseif nilargs[k] then
				return nil
			end
			local list = cfg.aliases[k];
			for _,arglist in ipairs(arg) do
				if type( list ) == 'table' then
					for _, alias_key in ipairs( list ) do
						if arglist[alias_key] then
							v = arglist[alias_key]
							break;
						end
					end
				elseif list ~= nil then
					v = arglist[list]
				end

				if v then
					break;
				end
			end
			if v == nil then
				nilargs[k] = true
			else
				rawset( tbl, k, v )
			end
			return v
		end,
	});
end

local function get_value_from_aliaes(aliases_tbl, arg_value)
	if arg_value  and aliases_tbl then
		for k, v_list in pairs(aliases_tbl) do
			if type(v_list) ~= "table" then
				if arg_value == v_list then
					return k
				end
			else
				for _, v_value in ipairs(v_list) do
					if arg_value == v_value then
						return k
					end
				end
			end
		end	
	end
end

local function eastern_numbers(thenumber)
	local str_number = tostring(thenumber)
	local ret_str = ''	
	for i=1,#str_number do
		ret_str = ret_str .. mw.ustring.char(0x0660 + tonumber(mw.ustring.sub(str_number,i,i)))
	end
	return ret_str
end

local function format_day(ctype,day)
	return (ctype =='hijri' and  use_mashreq_numbers and eastern_numbers(day) or day)
end

--[[------------------ Frame Functions-----------------]]

local function calendar(frame)
	local A,ret,month,year,cal,d,od,wd={},""
	local cday,cmonth,cmonth_days,ctype,oday,omonth,omonth_days,otype,oyear
	A[1] = frame:getParent().args[1] or  frame.args[1]
	A[2] = frame:getParent().args[2] or  frame.args[2]
	A[3] = frame:getParent().args[3] or  frame.args[3]
	A['رابط الشهر'] = frame:getParent().args['رابط الشهر'] or  frame.args['رابط الشهر'] or 'شهر '
	A['رابط اليوم'] = frame:getParent().args['رابط اليوم'] or  frame.args['رابط اليوم'] or ''
	A['style'] = frame:getParent().args['style'] or  frame.args['style']
	local alt_cal=1
	A['تقويم مقابل'] = frame:getParent().args['تقويم مقابل'] or  frame.args['تقويم مقابل'] or 'تلميح'
	if A['تقويم مقابل'] == '0' or A['تقويم مقابل'] == 'بدون' then
	    alt_cal = 0
	elseif A['تقويم مقابل'] == 'مخفي' or A['تقويم مقابل'] == 'تلميح' or A['تقويم مقابل'] == '1' then
	    alt_cal = 1
	elseif A['تقويم مقابل'] == 'ظاهر' or A['تقويم مقابل'] == '2'  then
	    alt_cal = 2
	end
	
	local hom = false
	if (frame:getParent().args['إخفاء خارج الشهر'] or  frame.args['إخفاء خارج الشهر'] ) == '1' then
		hom = true
	end
	
	local hide_p_n_month = false
	if (frame:getParent().args['إخفاء الشهر التالي/السابق'] or  frame.args['إخفاء الشهر التالي/السابق'] ) == '1' then
		hide_p_n_month = true
	end
	
	if (frame:getParent().args['الهجري بأرقام مشرقية'] or  frame.args['الهجري بأرقام مشرقية'] ) == '1' then
		use_mashreq_numbers = true
	end	

	local hide_year = false	
	if (frame:getParent().args['إخفاء السنة'] or  frame.args['إخفاء السنة'] ) == '1' then
		hide_year = true
	end	
	
	if A[3] then
		year=tonumber(A[3])
		if not year then
			return error("لم يتعرف على رقم السنة")
		end
	end
	if A[2] then
		month=tonumber(A[2])
		if not month then
			return error("لم يتعرف على رقم الشهر")
		end
	end
	
	cal = get_value_from_aliaes(cfg.cal_aliases, A[1]) or 'hijri'
	
	if not year then
		d=Date(cal)
		year=d.year
		month = month or d.month
		d:set_date(year,month,1)
	else
		d=Date(cal,year,month,1)
	end
	
	ret='<div class="d-calendar"' .. (A.style and (' style=' .. A.style) or '') .. '><div class="d-calendar-navigation">'
	.. (not hide_p_n_month and ('<div class="d-calendar-prev">[[' ..  A['رابط الشهر'] .. month_name(d.type,d.month-1) .. '|<<]]</div>') or '')
	.. '<div class="d-calendar-title">[[' .. A['رابط الشهر'] .. month_name(d.type,d.month) ..'|' .. month_name(d.type,d.month) .. ']]'
	.. (not hide_year and (' - [[' .. d.year .. (d.type=='hijri' and '  هـ' or '') .. ']]') or '') .. 	'</div>'
	.. (not hide_p_n_month and ('<div class="d-calendar-next">[[' .. A['رابط الشهر'] .. month_name(d.type,d.month+1) .. '|>>]]</div>') or '')
	.. '</div><div class="d-calendar-weekday"><ul><li>السبت</li><li>الأحد</li><li>الاثنين</li><li>الثلاثاء</li><li>الأربعاء</li><li>الخميس</li><li>الجمعة</li></ul></div>'
	.. '<div class="d-calendar-days"><ul>';
	
	if not hom and wday_reindex(d.wday)>0 then
		d:add(0,0,(0-wday_reindex(d.wday)))
	end
	if alt_cal>0 then
		if d.type=='hijri' then
			od=Date('gregorian',d.jd)
			otype='gregorian'
		else
			od=Date('hijri',d.jd)
			otype='hijri'
		end
		oday,omonth,oyear,omonth_days=od.day,od.month,od.year,od.month_days
		omonth_name=month_name(otype,omonth)
	end
	wd = wday_reindex(d.wday)
	ctype,cday,cmonth,cmonth_days=d.type,d.day,d.month,d.month_days
	cmonth_name=month_name(ctype,cmonth)
	
	while true do
		
		if hom and cday==1 and wd>0 then
			ret=ret .. '<li style="grid-column-start:' .. (wd + 1) .. '" class="d-calendar-current">'
		else
			ret=ret .. '<li' .. (cmonth==month and ' class="d-calendar-current">' or '>')
		end	
		
		if alt_cal == 2 then
			ret = ret .. '<span class="d-calendar-' .. ctype .. '">[[' .. A['رابط اليوم'] ..	cday .. ' ' .. cmonth_name .. '|' .. format_day(ctype,cday) .. ']]</span>'
			.. '<br><span class="d-calendar-sub d-calendar-' .. otype .. '">[[' .. A['رابط اليوم'] .. oday .. ' ' .. omonth_name .. '|' .. format_day(otype,oday) 
			.. (oday==1 and (' ' .. (otype=='hijri' and hijri_short_month(omonth) or omonth_name )) or '') .. ']]</span>';
		else
			ret = ret .. '<span class="d-calendar-only">[[' .. A['رابط اليوم'] ..	cday .. ' ' .. cmonth_name .. '|' .. format_day(ctype,cday) .. ']]</span>'
			if alt_cal == 1 then
				ret = ret	.. '<span class="d-calendar-sub-h">[[' .. A['رابط اليوم'] .. oday .. ' ' .. omonth_name .. ((string.len(A['رابط اليوم'])>0) and ('|' .. oday .. ' ' .. omonth_name) or '') .. ']] [[' .. oyear .. (otype=='hijri' and '  هـ' or '') .. ']]</span>';
			end
		end			
		ret = ret .. '</li>\n'; 
		cday=cday+1
		if cday>cmonth_days then
			if hom then
				break
			end
			d:add(0,0,cday-d.day)
			cday,cmonth,cmonth_days=d.day,d.month,d.month_days
			cmonth_name=month_name(ctype,cmonth)
		end
		
		if alt_cal>0 then
			oday=oday+1
			if oday>omonth_days then
				od:add(0,0,oday-od.day)
				oday,omonth,oyear,omonth_days=od.day,od.month,od.year,od.month_days
				omonth_name=month_name(otype,omonth)
			end
		end
		if wd==6 then
			if (month<12 and cmonth>month) or (month==12 and cmonth==1) then
				break
			else
				wd=0
			end
		else
			wd=wd+1
		end
	end
	ret = ret .. "</ul></div></div>"

	return ret

end

return {calendar=calendar}