欢迎来到奇葩栖息地!欢迎加入Discord服务器:XfrfHCzfbW请先至特殊:参数设置验证邮箱后再进行编辑。特殊:参数设置挑选自己想要使用的小工具!不会编辑?请至这里学习Wikitext语法。

模块:Chinese calendar:修订间差异

来自奇葩栖息地
添加的内容 删除的内容
(// Edit via Wikiplus)
标签已被回退
(//Edit via InPageEdit)
标签手工回退
第1行: 第1行:
local p = {}
local p = {}


-- 农历数据表
-- 位运算模拟函数
local lunarInfo = {
0x04bd8,
0x04ae0,
0x0a570,
0x054d5,
0x0d260,
0x0d950,
0x16554,
0x056a0,
0x09ad0,
0x055d2,
0x04ae0,
0x0a5b6,
0x0a4d0,
0x0d250,
0x1d255,
0x0b540,
0x0d6a0,
0x0ada2,
0x095b0,
0x14977,
0x04970,
0x0a4b0,
0x0b4b5,
0x06a50,
0x06d40,
0x1ab54,
0x02b60,
0x09570,
0x052f2,
0x04970,
0x06566,
0x0d4a0,
0x0ea50,
0x06e95,
0x05ad0,
0x02b60,
0x186e3,
0x092e0,
0x1c8d7,
0x0c950,
0x0d4a0,
0x1d8a6,
0x0b550,
0x056a0,
0x1a5b4,
0x025d0,
0x092d0,
0x0d2b2,
0x0a950,
0x0b557,
0x06ca0,
0x0b550,
0x15355,
0x04da0,
0x0a5b0,
0x14573,
0x052b0,
0x0a9a8,
0x0e950,
0x06aa0,
0x0aea6,
0x0ab50,
0x04b60,
0x0aae4,
0x0a570,
0x05260,
0x0f263,
0x0d950,
0x05b57,
0x056a0,
0x096d0,
0x04dd5,
0x04ad0,
0x0a4d0,
0x0d4d4,
0x0d250,
0x0d558,
0x0b540,
0x0b6a0,
0x195a6,
0x095b0,
0x049b0,
0x0a974,
0x0a4b0,
0x0b27a,
0x06a50,
0x06d40,
0x0af46,
0x0ab60,
0x09570,
0x04af5,
0x04970,
0x064b0,
0x074a3,
0x0ea50,
0x06b58,
0x055c0,
0x0ab60,
0x096d5,
0x092e0,
0x0c960,
0x0d954,
0x0d4a0,
0x0da50,
0x07552,
0x056a0,
0x0abb7,
0x025d0,
0x092d0,
0x0cab5,
0x0a950,
0x0b4a0,
0x0baa4,
0x0ad50,
0x055d9,
0x04ba0,
0x0a5b0,
0x15176,
0x052b0,
0x0a930,
0x07954,
0x06aa0,
0x0ad50,
0x05b52,
0x04b60,
0x0a6e6,
0x0a4e0,
0x0d260,
0x0ea65,
0x0d530,
0x05aa0,
0x076a3,
0x096d0,
0x04afb,
0x04ad0,
0x0a4d0,
0x1d0b6,
0x0d250,
0x0d520,
0x0dd45,
0x0b5a0,
0x056d0,
0x055b2,
0x049b0,
0x0a577,
0x0a4b0,
0x0aa50,
0x1b255,
0x06d20,
0x0ada0,
0x14b63,
0x09370,
0x049f8,
0x04970,
0x064b0,
0x168a6,
0x0ea50,
0x06b20,
0x1a6c4,
0x0aae0,
0x0a2e0,
0x0d2e3,
0x0c960,
0x0d557,
0x0d4a0,
0x0da50,
0x05d55,
0x056a0,
0x0a6d0,
0x055d4,
0x052d0,
0x0a9b8,
0x0a950,
0x0b4a0,
0x0b6a6,
0x0ad50,
0x055a0,
0x0aba4,
0x0a5b0,
0x052b0,
0x0b273,
0x06930,
0x07337,
0x06aa0,
0x0ad50,
0x14b55,
0x04b60,
0x0a570,
0x054e4,
0x0d160,
0x0e968,
0x0d520,
0x0daa0,
0x16aa6,
0x056d0,
0x04ae0,
0x0a9d4,
0x0a2d0,
0x0d150,
0x0f252,
0x0d520
}

-- 天干
local Gan = { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" }

-- 地支
local Zhi = { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" }

-- 月份
local nStr3 = { "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊" }

-- 日期
local nStr2 = { "初", "十", "廿", "卅" }
local nStr1 = { "日", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十" }

-- 实现位运算函数
local function band(a, b)
local function band(a, b)
a = tonumber(a) or 0
if not a or not b then return 0 end
b = tonumber(b) or 0
local result = 0
local result = 0
local bitval = 1
local bitval = 1


-- 转换为正整数处理
-- 处理负数或0的情况
if a <= 0 or b <= 0 then return 0 end
a = math.floor(math.abs(a))
b = math.floor(math.abs(b))


while a > 0 or b > 0 do
while a > 0 and b > 0 do
if a % 2 == 1 and b % 2 == 1 then
if a % 2 == 1 and b % 2 == 1 then
result = result + bitval
result = result + bitval
第23行: 第239行:
end
end


local function rshift(a, b)
-- 农历数据表
if not a or not b then return 0 end
local calendar = {
if a <= 0 then return 0 end
lunarInfo = { 0x04bd8,
0x04ae0,
if b < 0 then return a end
return math.floor(a / (2^b))
0x0a570,
end
0x054d5,
0x0d260,
0x0d950,
0x16554,
0x056a0,
0x09ad0,
0x055d2,
0x04ae0,
0x0a5b6,
0x0a4d0,
0x0d250,
0x1d255,
0x0b540,
0x0d6a0,
0x0ada2,
0x095b0,
0x14977,
0x04970,
0x0a4b0,
0x0b4b5,
0x06a50,
0x06d40,
0x1ab54,
0x02b60,
0x09570,
0x052f2,
0x04970,
0x06566,
0x0d4a0,
0x0ea50,
0x06e95,
0x05ad0,
0x02b60,
0x186e3,
0x092e0,
0x1c8d7,
0x0c950,
0x0d4a0,
0x1d8a6,
0x0b550,
0x056a0,
0x1a5b4,
0x025d0,
0x092d0,
0x0d2b2,
0x0a950,
0x0b557,
0x06ca0,
0x0b550,
0x15355,
0x04da0,
0x0a5b0,
0x14573,
0x052b0,
0x0a9a8,
0x0e950,
0x06aa0,
0x0aea6,
0x0ab50,
0x04b60,
0x0aae4,
0x0a570,
0x05260,
0x0f263,
0x0d950,
0x05b57,
0x056a0,
0x096d0,
0x04dd5,
0x04ad0,
0x0a4d0,
0x0d4d4,
0x0d250,
0x0d558,
0x0b540,
0x0b6a0,
0x195a6,
0x095b0,
0x049b0,
0x0a974,
0x0a4b0,
0x0b27a,
0x06a50,
0x06d40,
0x0af46,
0x0ab60,
0x09570,
0x04af5,
0x04970,
0x064b0,
0x074a3,
0x0ea50,
0x06b58,
0x055c0,
0x0ab60,
0x096d5,
0x092e0,
0x0c960,
0x0d954,
0x0d4a0,
0x0da50,
0x07552,
0x056a0,
0x0abb7,
0x025d0,
0x092d0,
0x0cab5,
0x0a950,
0x0b4a0,
0x0baa4,
0x0ad50,
0x055d9,
0x04ba0,
0x0a5b0,
0x15176,
0x052b0,
0x0a930,
0x07954,
0x06aa0,
0x0ad50,
0x05b52,
0x04b60,
0x0a6e6,
0x0a4e0,
0x0d260,
0x0ea65,
0x0d530,
0x05aa0,
0x076a3,
0x096d0,
0x04afb,
0x04ad0,
0x0a4d0,
0x1d0b6,
0x0d250,
0x0d520,
0x0dd45,
0x0b5a0,
0x056d0,
0x055b2,
0x049b0,
0x0a577,
0x0a4b0,
0x0aa50,
0x1b255,
0x06d20,
0x0ada0,
0x14b63,
0x09370,
0x049f8,
0x04970,
0x064b0,
0x168a6,
0x0ea50,
0x06b20,
0x1a6c4,
0x0aae0,
0x0a2e0,
0x0d2e3,
0x0c960,
0x0d557,
0x0d4a0,
0x0da50,
0x05d55,
0x056a0,
0x0a6d0,
0x055d4,
0x052d0,
0x0a9b8,
0x0a950,
0x0b4a0,
0x0b6a6,
0x0ad50,
0x055a0,
0x0aba4,
0x0a5b0,
0x052b0,
0x0b273,
0x06930,
0x07337,
0x06aa0,
0x0ad50,
0x14b55,
0x04b60,
0x0a570,
0x054e4,
0x0d160,
0x0e968,
0x0d520,
0x0daa0,
0x16aa6,
0x056d0,
0x04ae0,
0x0a9d4,
0x0a2d0,
0x0d150,
0x0f252,
0x0d520 },


-- 计算农历闰月月份
Gan = { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" },
local function leapMonth(y)
Zhi = { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" },
if y < 1900 or y > 2100 then return 0 end
Animals = { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" },
local index = y - 1900
nStr1 = { "日", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十" },
if index < 0 or index >= #lunarInfo then return 0 end
nStr2 = { "初", "十", "廿", "卅" },
return band(lunarInfo[index], 0xf)
nStr3 = { "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊" }
end
}


-- 核心转换函
-- 计算农历闰月天
function calendar.solar2lunar(y, m, d)
local function leapDays(y)
if y < 1900 or y > 2100 then return 0 end
-- 边界检查
local m = leapMonth(y)
if y < 1900 or y > 2100 then return nil end
if y == 1900 and m == 1 and d < 31 then return nil end
if m == 0 then return 0 end
if band(lunarInfo[y - 1900], 0x10000) ~= 0 then
return 30
end
return 29
end


-- 计算距离19001月31日的总天数
-- 计算农历年天数
local function lYearDays(y)
local objDate = os.time({ year = y, month = m, day = d })
if y < 1900 or y > 2100 then return 0 end
local sum = 348
local i = 0x8000
local idx = y - 1900
if idx < 0 or idx >= #lunarInfo then return 0 end

while i > 0x8 do
if band(lunarInfo[idx], i) ~= 0 then
sum = sum + 1
end
i = rshift(i, 1)
end
return sum + leapDays(y)
end

-- 计算农历月份天数
local function monthDays(y, m)
if y < 1900 or y > 2100 then return 0 end
if m > 12 or m < 1 then return 0 end
if band(lunarInfo[y - 1900], rshift(0x10000, m)) ~= 0 then
return 30
end
return 29
end

-- 主要的转换函数
function p.toLunar(frame)
-- 解析输入日期
local date = frame.args[1] or frame:getParent().args.date
if not date then return "日期参数错误" end

local y, m, d = date:match("^(%d%d%d%d)-(%d%d?)-(%d%d?)$")
if not y or not m or not d then
return "日期格式错误"
end
y, m, d = tonumber(y), tonumber(m), tonumber(d)

-- 验证日期范围
if y < 1900 or y > 2100 then
return "年份超出范围(1900-2100)"
end
if m < 1 or m > 12 then
return "月份错误"
end
if d < 1 or d > 31 then
return "日期错误"
end

-- 计算距离1900年1月31日的天数
local baseDate = os.time({ year = 1900, month = 1, day = 31 })
local baseDate = os.time({ year = 1900, month = 1, day = 31 })
local offset = math.floor((objDate - baseDate) / (24 * 60 * 60))
local targetDate = os.time({ year = y, month = m, day = d })
local offset = math.floor((targetDate - baseDate) / (24 * 60 * 60))

local i, temp, leap = 1900, 0, 0


-- 计算农历年
-- 计算农历年
local ly = 1900
while i < 2101 and offset > 0 do
temp = calendar.lYearDays(i)
local temp = 0
while ly < 2101 and offset > 0 do
temp = lYearDays(ly)
offset = offset - temp
offset = offset - temp
i = i + 1
ly = ly + 1
end
end

if offset < 0 then
if offset < 0 then
offset = offset + temp
offset = offset + temp
i = i - 1
ly = ly - 1
end
end


-- 计算农历月日
local year = i
local lm = 1
leap = calendar.leapMonth(year)
local ld = 1
local isLeap = false
local isLeap = false
local leap = leapMonth(ly)


-- 计算月
-- 计算月
while offset > 0 and lm < 13 do
i = 1
if leap > 0 and lm == leap + 1 and not isLeap then
while i < 13 and offset > 0 do
if leap > 0 and i == (leap + 1) and isLeap == false then
lm = lm - 1
i = i - 1
isLeap = true
isLeap = true
temp = calendar.leapDays(year)
temp = leapDays(ly)
else
else
temp = calendar.monthDays(year, i)
temp = monthDays(ly, lm)
end
end

if isLeap == true and i == (leap + 1) then
isLeap = false
end

offset = offset - temp
offset = offset - temp
i = i + 1
if isLeap and lm == leap + 1 then isLeap = false end
lm = lm + 1
end
end


-- 计算日
if offset == 0 and leap > 0 and i == leap + 1 then
if offset == 0 and leap > 0 and lm == leap + 1 then
if isLeap then
if isLeap then
isLeap = false
isLeap = false
else
else
isLeap = true
isLeap = true
i = i - 1
lm = lm - 1
end
end
end
end

if offset < 0 then
if offset < 0 then
offset = offset + temp
offset = offset + temp
i = i - 1
lm = lm - 1
end
end
ld = offset + 1


-- 格式化输出
local month = i
local day = offset + 1
local gzYear = Gan[((ly - 4) % 10) + 1] .. Zhi[((ly - 4) % 12) + 1]
local lMonth = nStr3[lm]

return {
local lDay
lYear = year,
if ld == 10 then
lMonth = month,
lDay = "初十"
lDay = day,
elseif ld == 20 then
isLeap = isLeap
lDay = "二十"
elseif ld == 30 then
}
lDay = "三十"
end

-- 辅助函数
function calendar.lYearDays(y)
local sum = 348
local info = calendar.lunarInfo[y - 1900]
if not info then return 0 end

for i = 0x8000, 0x8, -1 do
if band(info, i) ~= 0 then
sum = sum + 1
end
end
return sum + calendar.leapDays(y)
end

function calendar.leapMonth(y)
local info = calendar.lunarInfo[y - 1900]
if not info then return 0 end
return band(info, 0xf)
end

function calendar.leapDays(y)
local info = calendar.lunarInfo[y - 1900]
if not info then return 0 end
if calendar.leapMonth(y) ~= 0 then
return band(info, 0x10000) ~= 0 and 30 or 29
end
return 0
end

-- MediaWiki接口
function p.toLunar(frame)
local date = frame.args[1] or frame.args.date
if not date then
return '参数错误'
end

local y, m, d = date:match("(%d+)%-(%d+)%-(%d+)")
y, m, d = tonumber(y), tonumber(m), tonumber(d)

if not (y and m and d) then
return '日期格式错误'
end

local lunar = calendar.solar2lunar(y, m, d)
if not lunar then
return '超出计算范围(1900-2100)'
end

local result = calendar.Gan[(lunar.lYear - 4) % 10 + 1] ..
calendar.Zhi[(lunar.lYear - 4) % 12 + 1] .. '年'

if lunar.isLeap then
result = result .. '闰'
end

result = result .. calendar.nStr3[lunar.lMonth] .. '月'

if lunar.lDay < 11 then
result = result .. calendar.nStr2[1] .. calendar.nStr1[lunar.lDay]
elseif lunar.lDay < 20 then
result = result .. calendar.nStr2[2] .. calendar.nStr1[lunar.lDay - 10]
elseif lunar.lDay == 20 then
result = result .. calendar.nStr2[2] .. calendar.nStr2[2]
elseif lunar.lDay < 30 then
result = result .. calendar.nStr2[3] .. calendar.nStr1[lunar.lDay - 20]
else
else
result = result .. calendar.nStr2[4] .. calendar.nStr1[lunar.lDay - 30]
lDay = nStr2[math.floor(ld / 10) + 1] .. nStr1[ld % 10 + 1]
end
end


return result
return gzYear .. "年" .. lMonth .. "月" .. lDay
end
end



2025年1月9日 (四) 08:22的版本

[创建 | 历史 | 清除缓存]文档页面
此模块没有文档页面。如果你知道此模块的使用方法,请帮助为其创建文档页面。
local p = {}

-- 农历数据表
local lunarInfo = {
    0x04bd8,
    0x04ae0,
    0x0a570,
    0x054d5,
    0x0d260,
    0x0d950,
    0x16554,
    0x056a0,
    0x09ad0,
    0x055d2,
    0x04ae0,
    0x0a5b6,
    0x0a4d0,
    0x0d250,
    0x1d255,
    0x0b540,
    0x0d6a0,
    0x0ada2,
    0x095b0,
    0x14977,
    0x04970,
    0x0a4b0,
    0x0b4b5,
    0x06a50,
    0x06d40,
    0x1ab54,
    0x02b60,
    0x09570,
    0x052f2,
    0x04970,
    0x06566,
    0x0d4a0,
    0x0ea50,
    0x06e95,
    0x05ad0,
    0x02b60,
    0x186e3,
    0x092e0,
    0x1c8d7,
    0x0c950,
    0x0d4a0,
    0x1d8a6,
    0x0b550,
    0x056a0,
    0x1a5b4,
    0x025d0,
    0x092d0,
    0x0d2b2,
    0x0a950,
    0x0b557,
    0x06ca0,
    0x0b550,
    0x15355,
    0x04da0,
    0x0a5b0,
    0x14573,
    0x052b0,
    0x0a9a8,
    0x0e950,
    0x06aa0,
    0x0aea6,
    0x0ab50,
    0x04b60,
    0x0aae4,
    0x0a570,
    0x05260,
    0x0f263,
    0x0d950,
    0x05b57,
    0x056a0,
    0x096d0,
    0x04dd5,
    0x04ad0,
    0x0a4d0,
    0x0d4d4,
    0x0d250,
    0x0d558,
    0x0b540,
    0x0b6a0,
    0x195a6,
    0x095b0,
    0x049b0,
    0x0a974,
    0x0a4b0,
    0x0b27a,
    0x06a50,
    0x06d40,
    0x0af46,
    0x0ab60,
    0x09570,
    0x04af5,
    0x04970,
    0x064b0,
    0x074a3,
    0x0ea50,
    0x06b58,
    0x055c0,
    0x0ab60,
    0x096d5,
    0x092e0,
    0x0c960,
    0x0d954,
    0x0d4a0,
    0x0da50,
    0x07552,
    0x056a0,
    0x0abb7,
    0x025d0,
    0x092d0,
    0x0cab5,
    0x0a950,
    0x0b4a0,
    0x0baa4,
    0x0ad50,
    0x055d9,
    0x04ba0,
    0x0a5b0,
    0x15176,
    0x052b0,
    0x0a930,
    0x07954,
    0x06aa0,
    0x0ad50,
    0x05b52,
    0x04b60,
    0x0a6e6,
    0x0a4e0,
    0x0d260,
    0x0ea65,
    0x0d530,
    0x05aa0,
    0x076a3,
    0x096d0,
    0x04afb,
    0x04ad0,
    0x0a4d0,
    0x1d0b6,
    0x0d250,
    0x0d520,
    0x0dd45,
    0x0b5a0,
    0x056d0,
    0x055b2,
    0x049b0,
    0x0a577,
    0x0a4b0,
    0x0aa50,
    0x1b255,
    0x06d20,
    0x0ada0,
    0x14b63,
    0x09370,
    0x049f8,
    0x04970,
    0x064b0,
    0x168a6,
    0x0ea50,
    0x06b20,
    0x1a6c4,
    0x0aae0,
    0x0a2e0,
    0x0d2e3,
    0x0c960,
    0x0d557,
    0x0d4a0,
    0x0da50,
    0x05d55,
    0x056a0,
    0x0a6d0,
    0x055d4,
    0x052d0,
    0x0a9b8,
    0x0a950,
    0x0b4a0,
    0x0b6a6,
    0x0ad50,
    0x055a0,
    0x0aba4,
    0x0a5b0,
    0x052b0,
    0x0b273,
    0x06930,
    0x07337,
    0x06aa0,
    0x0ad50,
    0x14b55,
    0x04b60,
    0x0a570,
    0x054e4,
    0x0d160,
    0x0e968,
    0x0d520,
    0x0daa0,
    0x16aa6,
    0x056d0,
    0x04ae0,
    0x0a9d4,
    0x0a2d0,
    0x0d150,
    0x0f252,
    0x0d520
}

-- 天干
local Gan = { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" }

-- 地支
local Zhi = { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" }

-- 月份
local nStr3 = { "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊" }

-- 日期
local nStr2 = { "初", "十", "廿", "卅" }
local nStr1 = { "日", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十" }

-- 实现位运算函数
local function band(a, b)
    if not a or not b then return 0 end
    local result = 0
    local bitval = 1

    -- 处理负数或0的情况
    if a <= 0 or b <= 0 then return 0 end

    while a > 0 and b > 0 do
        if a % 2 == 1 and b % 2 == 1 then
            result = result + bitval
        end
        bitval = bitval * 2
        a = math.floor(a/2)
        b = math.floor(b/2)
    end
    return result
end

local function rshift(a, b)
    if not a or not b then return 0 end
    if a <= 0 then return 0 end
    if b < 0 then return a end
    return math.floor(a / (2^b))
end

-- 计算农历闰月月份
local function leapMonth(y)
    if y < 1900 or y > 2100 then return 0 end
    local index = y - 1900
    if index < 0 or index >= #lunarInfo then return 0 end
    return band(lunarInfo[index], 0xf)
end

-- 计算农历闰月天数
local function leapDays(y)
    if y < 1900 or y > 2100 then return 0 end
    local m = leapMonth(y)
    if m == 0 then return 0 end
    if band(lunarInfo[y - 1900], 0x10000) ~= 0 then
        return 30
    end
    return 29
end

-- 计算农历年天数
local function lYearDays(y)
    if y < 1900 or y > 2100 then return 0 end
    local sum = 348
    local i = 0x8000
    local idx = y - 1900
    if idx < 0 or idx >= #lunarInfo then return 0 end

    while i > 0x8 do
        if band(lunarInfo[idx], i) ~= 0 then
            sum = sum + 1
        end
        i = rshift(i, 1)
    end
    return sum + leapDays(y)
end

-- 计算农历月份天数
local function monthDays(y, m)
    if y < 1900 or y > 2100 then return 0 end
    if m > 12 or m < 1 then return 0 end
    if band(lunarInfo[y - 1900], rshift(0x10000, m)) ~= 0 then
        return 30
    end
    return 29
end

-- 主要的转换函数
function p.toLunar(frame)
    -- 解析输入日期
    local date = frame.args[1] or frame:getParent().args.date
    if not date then return "日期参数错误" end

    local y, m, d = date:match("^(%d%d%d%d)-(%d%d?)-(%d%d?)$")
    if not y or not m or not d then
        return "日期格式错误"
    end
    y, m, d = tonumber(y), tonumber(m), tonumber(d)

    -- 验证日期范围
    if y < 1900 or y > 2100 then
        return "年份超出范围(1900-2100)"
    end
    if m < 1 or m > 12 then
        return "月份错误"
    end
    if d < 1 or d > 31 then
        return "日期错误"
    end

    -- 计算距离1900年1月31日的天数
    local baseDate = os.time({ year = 1900, month = 1, day = 31 })
    local targetDate = os.time({ year = y, month = m, day = d })
    local offset = math.floor((targetDate - baseDate) / (24 * 60 * 60))

    -- 计算农历年
    local ly = 1900
    local temp = 0
    while ly < 2101 and offset > 0 do
        temp = lYearDays(ly)
        offset = offset - temp
        ly = ly + 1
    end
    if offset < 0 then
        offset = offset + temp
        ly = ly - 1
    end

    -- 计算农历月日
    local lm = 1
    local ld = 1
    local isLeap = false
    local leap = leapMonth(ly)

    -- 计算月
    while offset > 0 and lm < 13 do
        if leap > 0 and lm == leap + 1 and not isLeap then
            lm = lm - 1
            isLeap = true
            temp = leapDays(ly)
        else
            temp = monthDays(ly, lm)
        end
        offset = offset - temp
        if isLeap and lm == leap + 1 then isLeap = false end
        lm = lm + 1
    end

    -- 计算日
    if offset == 0 and leap > 0 and lm == leap + 1 then
        if isLeap then
            isLeap = false
        else
            isLeap = true
            lm = lm - 1
        end
    end
    if offset < 0 then
        offset = offset + temp
        lm = lm - 1
    end
    ld = offset + 1

    -- 格式化输出
    local gzYear = Gan[((ly - 4) % 10) + 1] .. Zhi[((ly - 4) % 12) + 1]
    local lMonth = nStr3[lm]
    local lDay
    if ld == 10 then
        lDay = "初十"
    elseif ld == 20 then
        lDay = "二十"
    elseif ld == 30 then
        lDay = "三十"
    else
        lDay = nStr2[math.floor(ld / 10) + 1] .. nStr1[ld % 10 + 1]
    end

    return gzYear .. "年" .. lMonth .. "月" .. lDay
end

return p