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

模块:Chinese calendar:修订间差异

来自奇葩栖息地
添加的内容 删除的内容
无编辑摘要
标签已被回退
(// Edit via Wikiplus)
标签已被回退
第2行: 第2行:


-- 位运算模拟函数
-- 位运算模拟函数
local function rshift(a, b)
if b < 0 then return lshift(a, -b) end
return math.floor(a / (2 ^ b))
end

local function lshift(a, b)
if b < 0 then return rshift(a, -b) end
return a * (2 ^ b)
end

local function band(a, b)
local function band(a, b)
a = tonumber(a) or 0
b = tonumber(b) or 0
local result = 0
local result = 0
local bitval = 1
local bitval = 1

while a > 0 and b > 0 do
-- 转换为正整数处理
a = math.floor(math.abs(a))
b = math.floor(math.abs(b))

while a > 0 or 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
end
end
bitval = bitval * 2
bitval = bitval * 2
a = math.floor(a / 2)
a = math.floor(a/2)
b = math.floor(b / 2)
b = math.floor(b/2)
end
end
return result
return result
第314行: 第311行:
function calendar.lYearDays(y)
function calendar.lYearDays(y)
local sum = 348
local sum = 348
local info = calendar.lunarInfo[y - 1900]
if not info then return 0 end

for i = 0x8000, 0x8, -1 do
for i = 0x8000, 0x8, -1 do
i = rshift(i, 1)
if band(info, i) ~= 0 then
if band(calendar.lunarInfo[y - 1900], i) ~= 0 then
sum = sum + 1
sum = sum + 1
end
end
第324行: 第323行:


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


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

2025年1月7日 (二) 16:12的版本

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

-- 位运算模拟函数
local function band(a, b)
    a = tonumber(a) or 0
    b = tonumber(b) or 0
    local result = 0
    local bitval = 1

    -- 转换为正整数处理
    a = math.floor(math.abs(a))
    b = math.floor(math.abs(b))

    while a > 0 or 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 calendar = {
    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 },

    Gan = { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" },
    Zhi = { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" },
    Animals = { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" },
    nStr1 = { "日", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十" },
    nStr2 = { "初", "十", "廿", "卅" },
    nStr3 = { "正", "二", "三", "四", "五", "六", "七", "八", "九", "十", "冬", "腊" }
}

-- 核心转换函数
function calendar.solar2lunar(y, m, d)
    -- 边界检查
    if y < 1900 or y > 2100 then return nil end
    if y == 1900 and m == 1 and d < 31 then return nil end

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

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

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

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

    local year = i
    leap = calendar.leapMonth(year)
    local isLeap = false

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

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

        offset = offset - temp
        i = i + 1
    end

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

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

    local month = i
    local day = offset + 1

    return {
        lYear = year,
        lMonth = month,
        lDay = day,
        isLeap = isLeap
    }
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
        result = result .. calendar.nStr2[4] .. calendar.nStr1[lunar.lDay - 30]
    end

    return result
end

return p