模組:沙盒/Willy1018/ChineseCalendar
外观
local p = {}
-- 天干與地支
local gan = {'甲','乙','丙','丁','戊','己','庚','辛','壬','癸'}
local zhi = {'子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥'}
-- 傳統月份名稱
local monthNames = {'正','二','三','四','五','六','七','八','九','十','冬','臘'}
-- 傳統日期名稱(1=初一, 2=初二, ..., 30=三十)
local dayNames = {
'初一','初二','初三','初四','初五','初六','初七','初八','初九','初十',
'十一','十二','十三','十四','十五','十六','十七','十八','十九','二十',
'廿一','廿二','廿三','廿四','廿五','廿六','廿七','廿八','廿九','三十'
}
-- 轉換格里曆或儒略曆為儒略日
function p.gregorianToJD(year, month, day)
-- 1月與2月視為前一年的第13與14月,有助於統一計算
if month <= 2 then
year = year - 1
month = month + 12
end
-- A 是世紀數(例如 2024 年 → A = 20)
local A = math.floor(year / 100)
local B
-- 格里曆(1582年10月15日及之後)
-- 根據格里曆改革:每 100 年不是閏年,但每 400 年是閏年
-- 所以需要修正
if year > 1582 or (year == 1582 and (month > 10 or (month == 10 and day >= 15))) then
-- 格里曆(1582年10月15日之後)
B = 2 - A + math.floor(A / 4)
elseif year == 1582 and month == 10 and day >= 5 and day <= 14 then
-- 曆法改革中不存在的日期
return nil, "錯誤:1582年10月5日至14日不存在(曆法改革)"
else
-- 儒略曆(1582年10月4日及以前)
-- 沒有使用修正項 B
B = 0
end
-- 儒略日計算公式(來自天文學標準公式)
local jd = math.floor(365.25 * (year + 4716)) +
math.floor(30.6001 * (month + 1)) +
day + B - 1524.5
return jd
end
-- 根據農曆年計算干支紀年(1984為甲子年)
function p.getGanZhiYear(year)
local offset = (year - 1984) % 60
return gan[(offset % 10) + 1] .. zhi[(offset % 12) + 1]
end
-- 假資料函數:從 JD 推出農曆資訊(實作中應改為真實算法)
function p.getLunarDate(jd)
-- 這裡可連結農曆演算法模組
return {
year = 2025,
month = 4,
isLeap = false,
day = 3
}
end
-- 主函數:輸入年月日 → 回傳「乙巳年四月初三」
function p.getLunarString(frame)
local y = tonumber(frame.args.year)
local m = tonumber(frame.args.month)
local d = tonumber(frame.args.day)
if not (y and m and d) then
return "錯誤:請提供 year、month、day"
end
local jd, err = p.gregorianToJD(y, m, d)
if not jd then
return err
end
local lunar = p.getLunarDate(jd)
local gz = p.getGanZhiYear(lunar.year)
local monthStr = (lunar.isLeap and '閏' or '') .. monthNames[lunar.month] .. '月'
local dayStr = dayNames[lunar.day]
return '今日是' .. gz .. '年' .. monthStr .. dayStr
end
return p