Bước tới nội dung

Mô đun:Âm lịch

Bách khoa toàn thư mở Wikipedia

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 endendlocal 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 = 367*Y - toint(7*(Y+toint((M+9)/12))/4) - toint(3*(toint((Y+(M-9)/7)/100)+1)/4) + toint(275*M/9)+D+1721028.5 else JD = 367*Y - toint(7*(Y+5001+toint((M-9)/7))/4) + toint(275*M/9)+D+1729776.5 end return JDendfunction 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 < 2299161) then A = Z else alpha = toint((Z-1867216.25)/36524.25) A = Z + 1 + alpha - toint(alpha/4) end B = A + 1524 C = toint((B-122.1)/365.25) D = toint(365.25*C) E = toint((B-D)/30.6001) dd = toint(B - D - toint(30.6001*E) + F) if E < 14 then mm = E - 1 else mm = E - 13 end if mm < 3 then yyyy = C - 4715 else yyyy = C - 4716; end return dd, mm, yyyyendlocal function LocalFromJD(JD, utc) return UniversalFromJD(JD + utc/24.0)endlocal function LocalToJD(D, M, Y, utc)-- D = tonumber(frame.args.D)-- M = tonumber(frame.args.M)-- Y = tonumber(frame.args.Y) return UniversalToJD(D, M, Y) - utc/24endlocal function NewMoon(k) pi = 3.14159265358979323846 local T = k/1236.85 -- Time in Julian centuries from 1900 January 0.5 local T2 = T * T local T3 = T2 * T local dr = math.pi/180 local Jd1 = 2415020.75933 + 29.53058868*k + 0.0001178*T2 - 0.000000155*T3 Jd1 = Jd1 + 0.00033*math.sin((166.56 + 132.87*T - 0.009173*T2)*dr) -- Mean new moon local M = 359.2242 + 29.10535608*k - 0.0000333*T2 - 0.00000347*T3 -- Sun's mean anomaly local Mpr = 306.0253 + 385.81691806*k + 0.0107306*T2 + 0.00001236*T3 -- Moon's mean anomaly local F = 21.2964 + 390.67050646*k - 0.0016528*T2 - 0.00000239*T3 -- Moon's argument of latitude local C1=(0.1734 - 0.000393*T)*math.sin(M*dr) + 0.0021*math.sin(2*dr*M) C1 = C1 - 0.4068*math.sin(Mpr*dr) + 0.0161*math.sin(dr*2*Mpr) C1 = C1 - 0.0004*math.sin(dr*3*Mpr) C1 = C1 + 0.0104*math.sin(dr*2*F) - 0.0051*math.sin(dr*(M+Mpr)) C1 = C1 - 0.0074*math.sin(dr*(M-Mpr)) + 0.0004*math.sin(dr*(2*F+M)) C1 = C1 - 0.0004*math.sin(dr*(2*F-M)) - 0.0006*math.sin(dr*(2*F+Mpr)) C1 = C1 + 0.0010*math.sin(dr*(2*F-Mpr)) + 0.0005*math.sin(dr*(2*Mpr+M)) local deltat if T < -11 then deltat= 0.001 + 0.000839*T + 0.0002261*T2 - 0.00000845*T3 - 0.000000081*T*T3 else deltat= -0.000278 + 0.000265*T + 0.000262*T2 end local JdNew = Jd1 + C1 - deltat return JdNewendlocal function SunLongitude(jdn) local T = (jdn - 2451545.0 ) / 36525 -- Time in Julian centuries from 2000-01-01 12:00:00 GMT local T2 = T*T local dr = math.pi/180 -- degree to radian local M = 357.52910 + 35999.05030*T - 0.0001559*T2 - 0.00000048*T*T2 -- mean anomaly, degree local L0 = 280.46645 + 36000.76983*T + 0.0003032*T2 -- mean longitude, degree local DL = (1.914600 - 0.004817*T - 0.000014*T2)*math.sin(dr*M) DL = DL + (0.019993 - 0.000101*T)*math.sin(dr*2*M) + 0.000290*math.sin(dr*3*M) local L = L0 + DL -- true longitude, degree L = L*dr L = L - math.pi*2*(toint(L/(math.pi*2))) -- Normalize to (0, 2*PI) return Lendlocal function LunarMonth11(Y, utc) local off = LocalToJD(31, 12, Y, utc) - 2415021.076998695 local k = toint(off / 29.530588853) local jd = NewMoon(k) local ret = {LocalFromJD(jd, utc)} local sunLong = SunLongitude(LocalToJD(ret[1], ret[2], ret[3], utc)) -- sun longitude at local midnight if sunLong > 3*math.pi/2 then jd = NewMoon(k-1) end return LocalFromJD(jd, utc)endlocal 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.pi*6) == math.floor(sl2/math.pi*6) 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 endendlocal 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 < LocalToJD(ly1[i], ly2[i], ly3[i], utc) and i > 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]}endfunction 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 endendlocal 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)endfunction 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 (nam*12+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 < 11 then return string.format ('mồng %d tháng %d%s năm %s', ngay, thang, nhuan, canchinam) else 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 endendp.Solar2Lunar = Solar2Lunar -- Dành cho [[Bản mẫu:Âm lịch/Bảng lịch]]return p