跳转到内容

模組:沙盒/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