Mô đun:Âm lịch

local p = {};

local function toint(n)
local s = tostring(n)
local i, j = s:find('%.')
if i then
return tonumber(s:sub(1, i-1))
else
return n
end
end

local function UniversalToJD(D, M, Y)
local JD
if (Y > 1582 or (Y 1582 and M > 10) or (Y 1582 and M == 10 and D > 14)) then
JD = 367Y - toint(7(Y+toint((M+9)/12))/4) - toint(3(toint((Y+(M-9)/7)/100)+1)/4) + toint(275M/9)+D+1721028.5
else
JD = 367Y - toint(7(Y+5001+toint((M-9)/7))/4) + toint(275M/9)+D+1729776.5
end
return JD
end

function UniversalFromJD(JD)
-- local JD = tonumber(frame.args.JD)
local Z, A, alpha, B, C, D, E, dd, mm, yyyy, F
Z = toint(JD+0.5)
F = (JD+0.5)-Z
if (Z 3math.pi/2 then
jd = NewMoon(k-1)
end
return LocalFromJD(jd, utc)
end

local function LunarYear(Y, b, utc)
local ret1 = {}
local ret2 = {}
local ret3 = {}
local ret4 = {}
local ret5 = {}
local month11A = {LunarMonth11(Y-1, utc)}
local jdMonth11A = LocalToJD(month11A[1], month11A[2], month11A[3], utc)
local k = math.floor(0.5 + (jdMonth11A - 2415021.076998695) / 29.530588853)
local month11B = {LunarMonth11(Y, utc)}
local off = LocalToJD(month11B[1], month11B[2], month11B[3], utc) - jdMonth11A
local leap
local retlength
local i
if off > 365.0 then
retlength = 14
leap = true
else
retlength = 13
leap = false
end
ret1[1] = month11A[1]
ret2[1] = month11A[2]
ret3[1] = month11A[3]
ret4[1] = 0
ret5[1] = 0
ret1[retlength] = month11B[1]
ret2[retlength] = month11B[2]
ret3[retlength] = month11B[3]
ret4[retlength] = 0
ret5[retlength] = 0
for i = 2, (retlength - 1) do
local nm = NewMoon(k+i-1)
local a = {LocalFromJD(nm, utc)}
ret1[i] = a[1]
ret2[i] = a[2]
ret3[i] = a[3]
ret4[i] = 0
ret5[i] = 0
end

for i = 1, retlength do
ret4[i] = math.mod(i + 10, 12)
end
if leap == true then
local sunLongitudes = {}
sunLongitudes[retlength+1] = 0
for i = 1, retlength do
local a = {ret1[i], ret2[i], ret3[i], ret4[i], ret5[i]}
local jdAtMonthBegin = LocalToJD(a[1], a[2], a[3], utc)
sunLongitudes[i] = SunLongitude(jdAtMonthBegin)
end
local found = false
for i = 1, retlength do
if found == true then
ret4[i] = math.mod(i+9, 12)
end
local sl1 = sunLongitudes[i]
local sl2 = sunLongitudes[i+1]
local hasMajorTerm
if math.floor(sl1/math.pi6) == math.floor(sl2/math.pi6) then
found = true
ret5[i] = 1
ret4[i] = math.mod(i+9, 12)
end
end
end
if b 1 then
return unpack(ret1)
else
if b 2 then
return unpack(ret2)
else
if b 3 then
return unpack(ret3)
else
if b 4 then
return unpack(ret4)
else
if b == 5 then
return unpack(ret5)
else
return retlength
end
end
end
end
end
end

local function Solar2Lunar(D, M, Y, utc)
local yy = Y
local ly1 = {LunarYear(Y,1, utc)}
local ly2 = {LunarYear(Y,2, utc)}
local ly3 = {LunarYear(Y,3, utc)}
local ly4 = {LunarYear(Y,4, utc)}
local ly5 = {LunarYear(Y,5, utc)}
local month11length = LunarYear(Y,6, utc)
local month11 = {ly1[month11length], ly2[month11length], ly3[month11length]}
local jdToday = LocalToJD(D, M, Y, utc)
local jdMonth11 = LocalToJD(month11[1], month11[2], month11[3], utc)
if (jdToday > jdMonth11 or jdToday == jdMonth11) then
ly1 = {LunarYear(Y+1,1, utc)}
ly2 = {LunarYear(Y+1,2, utc)}
ly3 = {LunarYear(Y+1,3, utc)}
ly4 = {LunarYear(Y+1,4, utc)}
ly5 = {LunarYear(Y+1,5, utc)}
yy = Y + 1
end
local i = LunarYear(Y,6, utc)
while jdToday 1 do
i = i -1
end
local dd = toint(jdToday - LocalToJD(ly1[i], ly2[i], ly3[i], utc)) + 1
local mm = ly4[i]
if mm >= 11 or mm == 0 then
yy = yy -1
end
return unpack{dd, mm, yy, ly5[i]}
end

function p.Lunar2Solar(frame)
D = tonumber(frame.args.D)
M = tonumber(frame.args.M)
Y = tonumber(frame.args.Y)
utc = tonumber(frame.args.utc)
DF = frame.args.DF
local leap = tonumber(frame.args.nhuan)
local yy = Y
if M>= 11 then
yy = Y + 1
end
local lm = {}
local lm1 = {LunarYear(yy, 1, utc)}
local lm2 = {LunarYear(yy, 2, utc)}
local lm3 = {LunarYear(yy, 3, utc)}
local lm4 = {LunarYear(yy, 4, utc)}
local lm5 = {LunarYear(yy, 5, utc)}
local length = LunarYear(yy, 6, utc)
local lunarMonth = {}
local jd
lunarMonth[1] = {"null"}
local i
if M == 12 then
M = 0
end
for i = 1, length do
lm = {lm1[i], lm2[i], lm3[i], lm4[i], lm5[i]}
if lm[4] M and lm[5] leap then
lunarMonth = {lm[1], lm[2], lm[3]}
break
end
end
if unpack{lunarMonth} == "null" then
return "Lỗi nhập!"
else
jd = LocalToJD(lunarMonth[1], lunarMonth[2], lunarMonth[3], utc)
local dmy = {LocalFromJD(jd + D - 1, utc)}
if DF 'full' then
return string.format ('ngày %d tháng %d năm %d', dmy[1], dmy[2], dmy[3])
else
if DF 'jMY' then
return string.format ('%d tháng %d năm %d', dmy[1], dmy[2], dmy[3])
else
if DF 'dFY' then
return string.format ('%02d tháng %02d năm %d', dmy[1], dmy[2], dmy[3])
else
if DF 'dm' then
return string.format ('%02d%02d', dmy[1], dmy[2])
else
if DF 'd-m-y' then
return string.format ('%02d-%02d-%02d', dmy[1], dmy[2], dmy[3])
else
if DF 'jM' then
return string.format ('%d tháng %d', dmy[1], dmy[2])
else
if DF 'dM' then
return string.format ('%02d tháng %d', dmy[1], dmy[2])
else
if DF 'Y' then
return string.format ('%02d', dmy[3])
else
if DF 'j' then
return string.format ('%d', dmy[1])
else
if DF 'd' then
return string.format ('%02d', dmy[1])
else
if DF 'n' then
return string.format ('%d', dmy[2])
else
if DF 'm' then
return string.format ('%02d', dmy[2])
else
if DF 'M' then
return string.format ('tháng %d', dmy[2])
else
if DF 'F' then
return string.format ('tháng %02d', dmy[2])
end end end end end end end end end end end end end end
end
end

local function canchi (x)
local a = x%10
local b = x%12
local can, chi
if a == 1 then
can = "Giáp"
else
if a == 2 then
can = "Ất"
else
if a == 3 then
can = "Bính"
else
if a == 4 then
can = "Đinh"
else
if a == 5 then
can = "Mậu"
else
if a == 6 then
can = "Kỷ"
else
if a == 7 then
can = "Canh"
else
if a == 8 then
can = "Tân"
else
if a == 9 then
can = "Nhâm"
else
if a == 0 then
can = "Quý"
end end end end end end end end end end
if b == 1 then
chi = "Tý"
else
if b == 2 then
chi = "Sửu"
else
if b == 3 then
chi = "Dần"
else
if b == 4 then
chi = "Mão"
else
if b == 5 then
chi = "Thìn"
else
if b == 6 then
chi = "Tỵ"
else
if b == 7 then
chi = "Ngọ"
else
if b == 8 then
chi = "Mùi"
else
if b == 9 then
chi = "Thân"
else
if b == 10 then
chi = "Dậu"
else
if b == 11 then
chi = "Tuất"
else
if b == 0 then
chi = "Hợi"
end end end end end end end end end end end end
return string.format ('%s %s', can, chi)
end

function p.main(frame)
D = tonumber(frame.args.D)
M = tonumber(frame.args.M)
Y = tonumber(frame.args.Y)
DF = frame.args.DF
utc = tonumber(frame.args.utc)
local ngay, thang, nam, nhuan
local LunarDM = {Solar2Lunar(D, M, Y, utc)}
ngay = LunarDM[1]
if LunarDM[2] == 0 then
thang = 12
else
thang = LunarDM[2]
end
nam = LunarDM[3]
local canchinam = canchi (nam+57)
local canchithang = canchi (nam12+thang+14)
local canchingay = canchi (toint(LocalToJD(D, M, Y, utc)+51.5))
if LunarDM[4] == 1 then
nhuan = " (nhuận)"
else
nhuan = ""
end
if DF 'full' and ngay 10 then
return string.format ('ngày %d tháng %d%s năm %s', ngay, thang, nhuan, canchinam)
else
if DF 'dm' then
return string.format ('%02d%02d', ngay, thang)
else
if DF 'jM' then
return string.format ('%d tháng %02d%s', ngay, thang, nhuan)
else
if DF 'dM' then
return string.format ('%02d tháng %d%s', ngay, thang, nhuan)
else
if DF 'Y' then
return string.format ('%s', canchi)
else
if DF 'j' then
return string.format ('%d', ngay)
else
if DF 'd' then
return string.format ('%02d', ngay)
else
if DF 'n' then
return string.format ('%d', thang)
else
if DF 'm' then
return string.format ('%02d', thang)
else
if DF 'M' then
return string.format ('tháng %d', thang)
else
if DF 'F' then
return string.format ('tháng %02d', thang)
else
if DF 'YY' then
return string.format ('%s', canchinam)
else
if DF 'MM' then
return string.format ('%s', canchithang)
else
if DF 'DD' then
return string.format ('%s', canchingay)
else
if DF == 'DDMMYY' then
return string.format ('ngày %s tháng %s năm %s', canchingay, canchithang, canchinam)
end end end end end end end end end end end end end end end end
end
return p