-- 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