پودمان:Iranian calendar/library

از اسلامیکال
پرش به ناوبری پرش به جستجو

توضیحات این پودمان می‌تواند در پودمان:Iranian calendar/library/توضیحات قرار گیرد.

-- This module is under development.

-- A library of Iranian calendar functions
-- Written and bringing more features by Alireza Eskandarpour Shoferi (@AEsShoferi) in Lua
-- Based on JalaliJSCalendar (by Ali Farhadi)
--
-- Distributed under the terms of the CC BY-SA 4.0

local p = {}

local daysMonth = {
	gregorian = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
	jalali = {31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29}
}

local gregorianWords = {
	abbrDays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
	abbrMonths = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"},
	days = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"},
	months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"},
	abbrClock = {"AM", "PM"}
}

local IranianWords = {
	abbrDays = {"یک", "دو", "سه", "چها", "پنج", "جمع", "شنب"},
	abbrMonths = {"فرو", "ارد", "خرد", "تیر", "مرد", "شهر", "مهر", "آبا", "آذر", "دی", "بهم", "اسف"},
	days = {"یک‌شنبه", "دوشنبه", "سه‌شنبه", "چهارشنبه", "پنج‌شنبه", "جمعه", "شنبه"},
	months = {"فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند"},
	abbrClock = {"ق.ظ", "ب.ظ"}
}

function p.jalaliToGregorian(frame)
	local jy = frame.args[1] -979
	local jm = frame.args[2] -1
	local jd = frame.args[3] -1

	local j_day_no = 365 * jy + math.floor(jy / 33) * 8 + math.floor((jy % 33 + 3) / 4)
	local i = 1
	while i <= jm do
		j_day_no = j_day_no + daysMonth.jalali[i]
		i = i + 1
	end

	j_day_no = j_day_no + jd

	local g_day_no = j_day_no + 79

	-- 146097 = 365*400 + 400/4 - 400/100 + 400/400
	local gy = 1600 + 400 * math.floor(g_day_no / 146097)
	g_day_no = g_day_no % 146097

	local leap = true
	-- 36525 = 365*100 + 100/4
	if (g_day_no >= 36525) then
		g_day_no = g_day_no - 1
		-- 36524 = 365*100 + 100/4 - 100/100
		gy = gy + 100 * math.floor(g_day_no / 36524)
		g_day_no = g_day_no % 36524

		if (g_day_no >= 365) then
			g_day_no = g_day_no + 1
		else
			leap = false
		end
	end

	-- 1461 = 365*4 + 4/4
	gy = gy + 4 * math.floor(g_day_no / 1461)
	g_day_no = g_day_no % 1461

	if (g_day_no >= 366) then
		leap = false

		g_day_no = g_day_no - 1
		gy = gy + math.floor(g_day_no / 365)
		g_day_no = g_day_no % 365
	end

	i = 1
	while g_day_no > daysMonth.gregorian[i] +((i == 1 and leap) and 1 or 0) do
		g_day_no = g_day_no - daysMonth.gregorian[i] +((i == 1 and leap) and 1 or 0)
		i = i + 1
	end
	local gm = i
	local gd = g_day_no + 1

	return {gy, gm, gd}
end

function p.checkDate(frame)
	return not(tonumber(frame.args[1]) < 0 or tonumber(frame.args[1]) > 32767 or tonumber(frame.args[2]) < 1 or tonumber(frame.args[2]) > 12 or tonumber(frame.args[3]) < 1 or tonumber(frame.args[3]) >
		(daysMonth.jalali[frame.args[2] -1] +((tonumber(frame.args[2]) == 12 and not((tonumber(frame.args[1]) -979) % 33 % 4)) and 1 or 0)))
end

function p.gregorianToJalali(frame)
	local gy = frame.args[1] -1600
	local gm = frame.args[2] -1
	local gd = frame.args[3] -1

	local g_day_no = 365 * gy + math.floor((gy + 3) / 4) - math.floor((gy + 99) / 100) + math.floor((gy + 399) / 400)

	local i = 1
	while i <= gm do
		g_day_no = g_day_no + daysMonth.gregorian[i]
		i = i + 1
	end
	if (gm > 1 and((gy % 4 == 0 and gy % 100 ~= 0) or(gy % 400 == 0))) then
		-- leap and after Feb
		g_day_no = g_day_no + 1
	end
	g_day_no = g_day_no + gd

	local j_day_no = g_day_no - 79

	local j_np = math.floor(j_day_no / 12053)
	j_day_no = j_day_no % 12053

	local jy = 979 + 33 * j_np + 4 * math.floor(j_day_no / 1461)

	j_day_no = j_day_no % 1461

	if (j_day_no >= 366) then
		jy = jy + math.floor((j_day_no - 1) / 365)
		j_day_no =(j_day_no - 1) % 365
	end

	i = 1
	while i <= 11 and j_day_no > daysMonth.jalali[i] do
		j_day_no = j_day_no - daysMonth.jalali[i]
		i = i + 1
	end
	local jm = i
	local jd = j_day_no + 1

	return {jy, jm, jd}
end

local function getJalaliDateInTable()
	local dateTable = os.date("*t")
	return p.gregorianToJalali({args={dateTable.year, dateTable.month + 1, dateTable.day}})
end

function p.getCurrentJalaliYear()
	return getJalaliDateInTable()[1]
end

function p.getCurrentJalaliMonth()
	return getJalaliDateInTable()[2] -1
end

-- Instructions about formatting: http://www.lua.org/pil/22.1.html
function p.getFormattedCurrentJalaliDate(frame)
	local gd = os.date("%d")
	local gm = os.date("%m")
	local gy = os.date("%Y")
	local j = p.gregorianToJalali({args={gy, gm + 1, gd}})
	return p.formatDate({args = {["format"] = frame.args["format"], j[1], j[2], j[3]}})
end

function p.formatDate(frame)
	-- پنج‌شنبه ۱۳ شهریور ۱۳۹۳ ۱۷:۰۹:۰۰ ب.ظ
	frame.args["format"] = frame.args["format"] or "%A %d %B %Y %H:%M:%S %p"
	if type(frame.args["in"]) ~= "nil" then
		if string.lower(frame.args["in"]) == "iranian" then
			local j = p.jalaliToGregorian({args = {frame.args[1], frame.args[2], frame.args[3]}})
			return os.date(frame.args["format"], os.time{year = j[1], month = j[2] - 1, day = j[3] + 1})
		else
			return os.date(frame.args["format"], os.time{year = frame.args[1], month = frame.args[2] - 1, day = frame.args[3] + 1})
		end
	else
		error("آرگومان in برای متد formatDate() یافت نشد.")
	end
end

function p.getCurrentJalaliDay()
	return getJalaliDateInTable()[3] +1
end

function p.getDifferentTime(frame)
	return os.difftime(frame.args[1], frame.args[2])
end

return p